├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── lint.yaml ├── .gitignore ├── .lintr ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── aaa-globals.R ├── augment-rprofile.R ├── available-packages.R ├── available-updates.R ├── bitbucket.R ├── bundle.R ├── cache.R ├── clean-search-path.R ├── cranlike-repositories.R ├── dependencies.R ├── descfile.R ├── disable.R ├── downloader.R ├── env.R ├── external.R ├── get-package-actions.R ├── git-prune.R ├── github.R ├── gitlab.R ├── hide-site-libraries.R ├── hooks.R ├── install-local.R ├── install.R ├── library-support.R ├── lockfile-metadata.R ├── lockfile.R ├── options.R ├── package-namespace-helpers.R ├── packrat-mode.R ├── packrat.R ├── paths.R ├── pkg.R ├── platform.R ├── pretty-print.R ├── r-hooks.R ├── read-lock-file.R ├── recursive-package-dependencies.R ├── remote-info.R ├── renv.R ├── restore-routines.R ├── restore.R ├── rstudio-protocol.R ├── search-path.R ├── snapshot.R ├── status.R ├── testthat-helpers.R ├── update.R ├── utils.R └── zzz.R ├── README.md ├── RELEASE.md ├── announce ├── packrat-0.2.0.md └── packrat-0.3.0.md ├── configure.R ├── cran-comments.md ├── inst ├── resources │ ├── init-rprofile.R │ ├── init.R │ └── mac_r_userlib.sh ├── rstudio │ └── rstudio-protocol └── vendor │ └── renv.R ├── internal ├── digestPkg.Rproj ├── digestPkg.sh ├── shinyPkg.sh └── testPkg.sh ├── man ├── appDependencies.Rd ├── bundle.Rd ├── clean.Rd ├── disable.Rd ├── init.Rd ├── install.Rd ├── install_local.Rd ├── lockfile-metadata.Rd ├── packify.Rd ├── packrat-external.Rd ├── packrat-mode.Rd ├── packrat-options.Rd ├── packrat-package.Rd ├── packrat-resources.Rd ├── repos_create.Rd ├── repos_upload.Rd ├── repository-management.Rd ├── restore.Rd ├── search_path.Rd ├── snapshot.Rd ├── snapshotImpl.Rd ├── status.Rd ├── unbundle.Rd └── unused_packages.Rd ├── packrat.Rproj ├── revdep ├── .gitignore ├── README.md ├── cran.md ├── failures.md └── problems.md ├── scenarios ├── git │ └── scenario-git-1.R └── helper-scenarios.R └── tests ├── test-cranlike-repositories.R ├── testthat.R └── testthat ├── .gitignore ├── Ugly, but legal, path for a project (long) ├── bread │ └── DESCRIPTION ├── breakfast │ └── DESCRIPTION ├── oatmeal │ └── DESCRIPTION ├── packrat │ └── DESCRIPTION └── toast │ └── DESCRIPTION ├── _snaps └── pkg.md ├── lockfiles └── lockfile-multipleRepos.txt ├── other-packages └── packrat │ └── DESCRIPTION ├── packages ├── bread │ └── DESCRIPTION ├── breakfast │ └── DESCRIPTION ├── egg │ └── DESCRIPTION ├── oatmeal │ └── DESCRIPTION └── toast │ └── DESCRIPTION ├── projects ├── carbs │ └── flour.R ├── empty │ └── empty.R ├── emptydesc │ ├── DESCRIPTION │ └── app.R ├── falsy-bitbucket │ ├── deps.R │ └── packrat │ │ └── packrat.lock ├── falsy-gitlab │ ├── deps.R │ └── packrat │ │ └── packrat.lock ├── healthy │ └── healthy.R ├── libraries │ ├── library.R │ └── packrat │ │ ├── lib │ │ └── lib-current.R │ │ ├── library.new │ │ └── lib-new.R │ │ └── library.old │ │ └── lib-old.R ├── partlyignored │ ├── ignoreme │ │ └── ignorethis.R │ └── notignored.R ├── sated │ └── sated.R └── smallbreakfast │ ├── bread.R │ └── oatmeal.R ├── resources ├── alternate-engines.Rmd ├── broken-chunks.Rmd ├── dependencies.qmd ├── descriptions │ ├── falsy.packrat │ ├── falsy.remotes │ ├── github │ ├── github_subdir │ ├── gitlab │ └── gitlab_subdir ├── emoji.R ├── emoji.Rmd ├── evaluate-deps.Rmd ├── interactive-doc-example.Rmd ├── knitr-minimal.Rnw ├── loading-packages.R ├── no-chunks.Rmd ├── params-example.Rmd ├── simple.qmd ├── test-sweave.Rnw └── unknown-engines.Rmd ├── test-aaa.R ├── test-bitbucket.R ├── test-bundle.R ├── test-cache.R ├── test-dependencies.R ├── test-downloader.R ├── test-env.R ├── test-git.R ├── test-github.R ├── test-gitlab.R ├── test-hash.R ├── test-ignores.R ├── test-install.R ├── test-local-repositories.R ├── test-lockfile.R ├── test-options.R ├── test-packrat-mode.R ├── test-packrat.R ├── test-pkg.R ├── test-remote-info.R ├── test-restore.R ├── test-rmarkdown.R ├── test-shiny.R ├── test-utils.R └── test-with_extlib.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^internal$ 4 | ^packrat$ 5 | ^announce$ 6 | ^scenarios$ 7 | ^configure\.R$ 8 | ^NEWS\.md$ 9 | ^RELEASE\.md$ 10 | ^\.Rprofile$ 11 | ^\.github$ 12 | ^\.lintr$ 13 | ^tags$ 14 | ^R/tags$ 15 | ^cran-comments\.md$ 16 | ^revdep$ 17 | ^CRAN-SUBMISSION$ 18 | ^tests/testthat/packrat/lib$ 19 | ^tests/testthat/packrat/lib-R$ 20 | ^tests/testthat/packrat/lib-ext$ 21 | ^tests/testthat/repo$ 22 | ^tests/testthat/repo-empty$ 23 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag. 2 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | - {os: ubuntu-latest, r: 'oldrel-2'} 27 | - {os: ubuntu-latest, r: 'oldrel-3'} 28 | - {os: ubuntu-latest, r: 'oldrel-4'} 29 | 30 | env: 31 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 32 | R_KEEP_PKG_SOURCE: yes 33 | 34 | steps: 35 | - uses: actions/checkout@v2 36 | 37 | - uses: r-lib/actions/setup-pandoc@v2 38 | 39 | - uses: r-lib/actions/setup-r@v2 40 | with: 41 | r-version: ${{ matrix.config.r }} 42 | http-user-agent: ${{ matrix.config.http-user-agent }} 43 | use-public-rspm: true 44 | 45 | - uses: r-lib/actions/setup-r-dependencies@v2 46 | with: 47 | extra-packages: any::rcmdcheck 48 | needs: check 49 | 50 | - uses: r-lib/actions/check-r-package@v2 51 | with: 52 | upload-snapshots: true 53 | -------------------------------------------------------------------------------- /.github/workflows/lint.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 | 9 | name: lint 10 | 11 | jobs: 12 | lint: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - uses: r-lib/actions/setup-r@v2 20 | with: 21 | use-public-rspm: true 22 | 23 | - uses: r-lib/actions/setup-r-dependencies@v2 24 | with: 25 | extra-packages: any::lintr, local::. 26 | needs: lint 27 | 28 | - name: Lint 29 | run: lintr::lint_package() 30 | shell: Rscript {0} 31 | env: 32 | LINTR_ERROR_ON_LINT: true 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .Rproj.user 3 | .Rhistory 4 | tests/testthat/packrat/ 5 | packrat-scenario*/ 6 | packrat/lib*/ 7 | -------------------------------------------------------------------------------- /.lintr: -------------------------------------------------------------------------------- 1 | linters: linters_with_defaults( 2 | # some tests have _VERY_ long expectations. 3 | indentation_linter = NULL, 4 | line_length_linter(270), 5 | object_length_linter(80), 6 | object_name_linter = NULL, 7 | object_usage_linter = NULL, 8 | brace_linter = NULL, 9 | commented_code_linter = NULL, 10 | cyclocomp_linter = NULL, 11 | quotes_linter = NULL, 12 | seq_linter = NULL 13 | ) 14 | exclusions: list( 15 | # renv is vendored code, not ours. 16 | "inst/vendor/renv.R", 17 | # test resources that are not "source". 18 | "tests/testthat/lockfiles", 19 | "tests/testthat/other-packages", 20 | "tests/testthat/packrat", 21 | "tests/testthat/projects", 22 | "tests/testthat/repo", 23 | "tests/testthat/repo-empty", 24 | "tests/testthat/resources" 25 | ) 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Type: Package 2 | Package: packrat 3 | Title: A Dependency Management System for Projects and their R Package 4 | Dependencies 5 | Version: 0.9.2.9000 6 | Authors@R: c( 7 | person("Aron", "Atkins", , "aron@posit.co", role = c("aut", "cre")), 8 | person("Toph", "Allen", role = "aut"), 9 | person("Kevin", "Ushey", role = "aut"), 10 | person("Jonathan", "McPherson", role = "aut"), 11 | person("Joe", "Cheng", role = "aut"), 12 | person("JJ", "Allaire", role = "aut"), 13 | person("Posit Software, PBC", role = c("cph", "fnd")) 14 | ) 15 | Description: Manage the R packages your project depends on in an isolated, 16 | portable, and reproducible way. 17 | License: GPL-2 18 | URL: https://github.com/rstudio/packrat 19 | BugReports: https://github.com/rstudio/packrat/issues 20 | Depends: 21 | R (>= 3.0.0) 22 | Imports: 23 | tools, 24 | utils 25 | Suggests: 26 | devtools, 27 | httr, 28 | knitr, 29 | mockery, 30 | rmarkdown, 31 | testthat (>= 3.0.0) 32 | Config/testthat/edition: 3 33 | Encoding: UTF-8 34 | RoxygenNote: 7.2.3 35 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(.snapshotImpl) 4 | export(bundle) 5 | export(bundles_dir) 6 | export(clean) 7 | export(disable) 8 | export(extlib) 9 | export(get_lockfile_metadata) 10 | export(get_opts) 11 | export(init) 12 | export(install) 13 | export(install_local) 14 | export(lib_dir) 15 | export(off) 16 | export(on) 17 | export(opts) 18 | export(packify) 19 | export(packrat_lib) 20 | export(packrat_mode) 21 | export(project_dir) 22 | export(repos_add) 23 | export(repos_add_local) 24 | export(repos_create) 25 | export(repos_list) 26 | export(repos_remove) 27 | export(repos_set) 28 | export(repos_set_local) 29 | export(repos_upload) 30 | export(restore) 31 | export(search_path) 32 | export(set_lockfile_metadata) 33 | export(set_opts) 34 | export(snapshot) 35 | export(src_dir) 36 | export(status) 37 | export(unbundle) 38 | export(unused_packages) 39 | export(user_lib) 40 | export(with_extlib) 41 | import(utils) 42 | importFrom(tools,md5sum) 43 | importFrom(tools,pkgVignettes) 44 | -------------------------------------------------------------------------------- /R/aaa-globals.R: -------------------------------------------------------------------------------- 1 | .packrat <- new.env(parent = emptyenv()) 2 | .packrat$repos <- new.env(parent = emptyenv()) 3 | .packrat$packratFormat <- "1.4" 4 | .packrat$options <- NULL 5 | 6 | ## Mutable values that might be modified by the user (code borrowed from knitr) 7 | # merge elements of y into x with the same names 8 | merge_list <- function(x, y) { 9 | x[names(y)] <- y 10 | x 11 | } 12 | 13 | new_defaults <- function(value = list()) { 14 | defaults <- value 15 | 16 | get <- function(name, default = FALSE, drop = TRUE) { 17 | if (default) defaults <- value # this is only a local version 18 | if (missing(name)) defaults else { 19 | if (drop && length(name) == 1) defaults[[name]] else { 20 | setNames(defaults[name], name) 21 | } 22 | } 23 | } 24 | set <- function(...) { 25 | dots <- list(...) 26 | if (length(dots) == 0) return() 27 | if (is.null(names(dots)) && length(dots) == 1 && is.list(dots[[1]])) 28 | if (length(dots <- dots[[1]]) == 0) return() 29 | defaults <<- merge(dots) 30 | invisible(NULL) 31 | } 32 | merge <- function(values) merge_list(defaults, values) 33 | restore <- function(target = value) defaults <<- target 34 | 35 | list(get = get, set = set, merge = merge, restore = restore) 36 | } 37 | 38 | ## These should be set on entering, exiting packrat mode 39 | .packrat_mutables <- new_defaults(list( 40 | origLibPaths = NULL, 41 | project = NULL 42 | )) 43 | 44 | # Work around namespace:stats potentially not being loaded 45 | setNames <- function(object = nm, nm) { 46 | names(object) <- nm 47 | object 48 | } 49 | -------------------------------------------------------------------------------- /R/augment-rprofile.R: -------------------------------------------------------------------------------- 1 | ## Augment the .Rprofile for a project -- if it doesn't exist, just copy 2 | ## from packrat; if it does, check it and add if necessary 3 | augmentRprofile <- function(project = NULL) { 4 | 5 | project <- getProjectDir(project) 6 | path <- file.path(project, ".Rprofile") 7 | 8 | if (!file.exists(path)) { 9 | file.copy( 10 | instInitRprofileFilePath(), 11 | path 12 | ) 13 | } else { 14 | editRprofileAutoloader(project, "update") 15 | } 16 | } 17 | 18 | # edit the .Rprofile for this project 19 | editRprofileAutoloader <- function(project, action = c("update", "remove")) { 20 | 21 | # resolve action argument 22 | action <- match.arg(action) 23 | 24 | # if the .Rprofile doesn't exist, create it 25 | if (!file.exists(file.path(project, ".Rprofile"))) 26 | file.create(file.path(project, ".Rprofile")) 27 | 28 | ## Read the .Rprofile in and see if it's been packified 29 | path <- file.path(project, ".Rprofile") 30 | .Rprofile <- readLines(path) 31 | packifyStart <- grep("#### -- Packrat Autoloader", .Rprofile, fixed = TRUE) 32 | packifyEnd <- grep("#### -- End Packrat Autoloader -- ####", .Rprofile, fixed = TRUE) 33 | 34 | if (length(packifyStart) && length(packifyEnd)) 35 | .Rprofile <- .Rprofile[-c(packifyStart:packifyEnd)] 36 | 37 | ## Append init.R to the .Rprofile if needed 38 | if (identical(action, "update")) 39 | .Rprofile <- c(.Rprofile, readLines(instInitRprofileFilePath())) 40 | 41 | ## if the .Rprofile is now empty, delete it 42 | if (identical(gsub("[[:space:]]", "", unique(.Rprofile)), "") || 43 | !length(.Rprofile)) 44 | file.remove(file.path(project, ".Rprofile")) 45 | else 46 | cat(.Rprofile, file = path, sep = "\n") 47 | 48 | invisible() 49 | } 50 | -------------------------------------------------------------------------------- /R/available-packages.R: -------------------------------------------------------------------------------- 1 | defaultRepositoryDbFields <- function() { 2 | c( 3 | "Package", 4 | "Version", 5 | "Priority", 6 | "Depends", 7 | "Imports", 8 | "LinkingTo", 9 | "Suggests", 10 | "Enhances", 11 | "License", 12 | "License_is_FOSS", 13 | "License_restricts_use", 14 | "OS_type", 15 | "Archs", 16 | "MD5sum", 17 | "NeedsCompilation" 18 | ) 19 | } 20 | 21 | availablePackagesSkeleton <- function() { 22 | 23 | tools <- asNamespace("tools") 24 | defaults <- tryCatch( 25 | tools$.get_standard_repository_db_fields(type = "source"), 26 | error = identity 27 | ) 28 | 29 | if (inherits(defaults, "error")) 30 | defaults <- defaultRepositoryDbFields() 31 | 32 | fields <- c(defaults, "File", "Repository") 33 | 34 | data <- array( 35 | character(), 36 | dim = c(0L, length(fields)), 37 | dimnames = list(NULL, fields) 38 | ) 39 | 40 | data 41 | } 42 | 43 | availablePackagesBinary <- function(repos = getOption("repos")) { 44 | availablePackages(repos = repos, type = .Platform$pkgType) 45 | } 46 | 47 | availablePackagesSource <- function(repos = getOption("repos")) { 48 | availablePackages(repos = repos, type = "source") 49 | } 50 | 51 | hasBinaryRepositories <- function() { 52 | !identical(.Platform$pkgType, "source") 53 | } 54 | 55 | binaryRepositoriesEnabled <- function() { 56 | !identical(getOption("pkgType"), "source") 57 | } 58 | 59 | availablePackages <- function(repos = getOption("repos"), 60 | type = getOption("pkgType")) 61 | { 62 | # check cache for entry 63 | key <- paste(deparse(repos), deparse(type), sep = " ", collapse = " ") 64 | if (!is.null(.packrat$repos[[key]])) 65 | return(.packrat$repos[[key]]) 66 | 67 | # catch errors related to e.g. missing PACKAGES file (could happen for 68 | # source-only repositories, if we tried to query a binary repository) 69 | # 70 | # NOTE: older versions of R don't support the 'repos' argument to 71 | # available.packages 72 | result <- tryCatch( 73 | available.packages( 74 | contriburl = utils::contrib.url(repos, type), 75 | type = type 76 | ), 77 | error = function(e) { 78 | availablePackagesSkeleton() 79 | } 80 | ) 81 | 82 | # cache and return 83 | .packrat$repos[[key]] <- result 84 | result 85 | } 86 | -------------------------------------------------------------------------------- /R/bitbucket.R: -------------------------------------------------------------------------------- 1 | # - Equivalent to other git provider download functions. 2 | # - Called by `getSourceForPkgRecord` (which manages the lifecycle of 3 | # `destfile`). Responsible for dispatching different download implementations 4 | # depending on environment and configuration, passing them `url` and 5 | # `destfile`. 6 | # - Returns nothing if successful, and does not check the return values of inner 7 | # download methods (`renvDownload`, `providerDownloadHttr`, and 8 | # `downloadWithRetries`). Those functions are responsible for detecting errors 9 | # and calling `stop` when they occur. 10 | # - For authenticated download methods (`renvDownload`, `providerDownloadHttr`), 11 | # catches errors append a note advising the user to check 12 | # configuration-related environment variables. This happens no matter what the 13 | # cause of the error. 14 | bitbucketDownload <- function(url, destfile, ...) { 15 | if (bitbucketAuthenticated() && canUseRenvDownload()) { 16 | tryCatch(renvDownload(url, destfile, type = "bitbucket"), error = authDownloadAdvice("bitbucket", TRUE, "renv")) 17 | } else if (bitbucketAuthenticated() && canUseHttr()) { 18 | tryCatch(bitbucketDownloadHttr(url, destfile), error = authDownloadAdvice("bitbucket", TRUE, "httr")) 19 | } else { 20 | tryCatch(downloadWithRetries(url, destfile = destfile), error = authDownloadAdvice("bitbucket", FALSE, "internal")) 21 | } 22 | } 23 | 24 | # - The original function for authenticated downloads. Requires `httr` to be 25 | # installed. Called by this git provider's top-level download function if 26 | # `renvDownload`'s requirements are not met, but this function's are. 27 | # - Returns `TRUE` if it succeeds. Calls `stop()` if any errors are encountered. 28 | # - Writes to `destfile`, whose lifecycle is managed by `getSourceForPkgRecord`. 29 | bitbucketDownloadHttr <- function(url, destfile, ...) { 30 | authenticate <- yoink("httr", "authenticate") 31 | GET <- yoink("httr", "GET") 32 | content <- yoink("httr", "content") 33 | 34 | user <- bitbucket_user(quiet = TRUE) 35 | pwd <- bitbucket_pwd(quiet = TRUE) 36 | auth <- if (!is.null(user) && !is.null(pwd)) { 37 | authenticate(user, pwd, type = "basic") 38 | } else { 39 | list() 40 | } 41 | 42 | result <- GET(url, auth) 43 | if (result$status != 200) { 44 | stop(httr::http_status(result)$message) 45 | } 46 | writeBin(content(result, "raw"), destfile) 47 | if (!file.exists(destfile)) { 48 | stop("No data received.") 49 | } 50 | # Success! 51 | return(TRUE) 52 | } 53 | 54 | bitbucketArchiveUrl <- function(pkgRecord) { 55 | # API URLs get recorded when packages are downloaded with devtools / 56 | # remotes, but Packrat just wants to use 'plain' URLs when downloading 57 | # package sources. 58 | remoteHost <- sub("api.bitbucket.org/2.0", 59 | "bitbucket.org", 60 | pkgRecord$remote_host, 61 | fixed = TRUE) 62 | 63 | fmt <- "%s/%s/%s/get/%s.tar.gz" 64 | archiveUrl <- sprintf(fmt, 65 | remoteHost, 66 | pkgRecord$remote_username, 67 | pkgRecord$remote_repo, 68 | pkgRecord$remote_sha) 69 | 70 | # Ensure the protocol is prepended. We prefer using https if possible. Note 71 | # that 'wininet' can fail if attempting to download from an 'http' URL that 72 | # redirects to an 'https' URL. https://github.com/rstudio/packrat/issues/269 73 | method <- tryCatch( 74 | secureDownloadMethod(), 75 | error = function(e) "internal" 76 | ) 77 | protocol <- if (identical(method, "internal")) "http" else "https" 78 | if (!grepl("^http", archiveUrl)) { 79 | archiveUrl <- paste(protocol, archiveUrl, sep = "://") 80 | } 81 | return(archiveUrl) 82 | } 83 | 84 | isBitbucketURL <- function(url) { 85 | is.string(url) && grepl("^http(?:s)?://(?:www|api).bitbucket.(org|com)", url, perl = TRUE) 86 | } 87 | 88 | bitbucketAuthenticated <- function() { 89 | !is.null(bitbucket_user(quiet = TRUE)) && 90 | !is.null(bitbucket_pwd(quiet = TRUE)) 91 | } 92 | 93 | bitbucket_user <- function(quiet = TRUE) { 94 | user <- Sys.getenv("BITBUCKET_USERNAME") 95 | if (nzchar(user)) { 96 | if (!quiet) { 97 | message("Using Bitbucket username from envvar BITBUCKET_USERNAME") 98 | } 99 | return(user) 100 | } 101 | return(NULL) 102 | } 103 | 104 | bitbucket_pwd <- function(quiet = TRUE) { 105 | pwd <- Sys.getenv("BITBUCKET_PASSWORD") 106 | if (nzchar(pwd)) { 107 | if (!quiet) { 108 | message("Using Bitbucket password from envvar BITBUCKET_PASSWORD") 109 | } 110 | return(pwd) 111 | } 112 | return(NULL) 113 | } 114 | -------------------------------------------------------------------------------- /R/clean-search-path.R: -------------------------------------------------------------------------------- 1 | ## Clean up the search path -- unload all packages in the user library 2 | ## Primarily used when entering packrat mode 3 | cleanSearchPath <- function(verbose = TRUE, lib.loc = getUserLibPaths()) { 4 | 5 | searchPath <- search_path() 6 | 7 | ## Don't remove anything in a packrat private library 8 | toCheck <- grep("packrat", searchPath$lib.dir, invert = TRUE) 9 | if (!length(toCheck)) return(NULL) 10 | 11 | searchPath <- searchPath[toCheck, ] 12 | 13 | searchPath$path <- paste("package", searchPath$package, sep = ":") 14 | ip <- utils::installed.packages(lib.loc = lib.loc) 15 | searchPath <- searchPath[searchPath$package %in% rownames(ip), ] 16 | 17 | ## Don't unload base, recommended packages 18 | userPkgs <- searchPath$package[is.na(ip[searchPath$package, "Priority"])] 19 | searchPathToUnload <- searchPath[searchPath$package %in% userPkgs, ] 20 | 21 | if (verbose && nrow(searchPathToUnload)) { 22 | message("Unloading packages in user library:\n- ", paste(searchPathToUnload$package, collapse = ", ")) 23 | } 24 | 25 | for (path in searchPathToUnload$path) { 26 | forceUnload(path) 27 | } 28 | 29 | searchPathToUnload 30 | } 31 | -------------------------------------------------------------------------------- /R/descfile.R: -------------------------------------------------------------------------------- 1 | 2 | # ensure that a file ends with a single newline 3 | normalizeDcf <- function(path) { 4 | n <- file.info(path)$size 5 | contents <- readChar(path, n, TRUE) 6 | replaced <- gsub("\n*$", "", contents) 7 | if (!identical(contents, replaced)) 8 | cat(replaced, file = path, sep = "\n") 9 | path 10 | } 11 | 12 | appendToDcf <- function(path, records) { 13 | normalizeDcf(path) 14 | records <- Filter(length, records) 15 | write_dcf(records, path, append = TRUE) 16 | } 17 | 18 | # Combines one or more comma-delimited fields from a data frame read from a 19 | # DCF. 20 | combineDcfFields <- function(dcfFrame, fields) { 21 | unique(unlist(lapply(fields, function(field) { 22 | gsub("\\s.*", "", unlist( 23 | strsplit( 24 | gsub("^\\s*", "", as.character(dcfFrame[[field]])), "\\s*,\\s*"))) 25 | }))) 26 | } 27 | -------------------------------------------------------------------------------- /R/disable.R: -------------------------------------------------------------------------------- 1 | #' Disable the use of Packrat in a Project 2 | #' 3 | #' Disable packrat within a project, reverting to the use of standard user 4 | #' package libraries. 5 | #' 6 | #' @param project The directory in which packrat will be disabled (defaults to 7 | #' the current working directory) 8 | #' @param restart If \code{TRUE}, restart the R session after disabling packrat. 9 | #' 10 | #' @note Disabling packrat for a project removes the packrat initialization code 11 | #' from the .Rprofile file, resulting in the use of standard user package 12 | #' libraries. Note that the \code{packrat} directory is not deleted, but remains 13 | #' unused. 14 | #' 15 | #' To re-enable the use of packrat for a project you can call the 16 | #' \code{\link{init}} function. 17 | #' 18 | #' The \code{restart} parameter will only result in a restart of R when the R 19 | #' environment packrat is running within makes available a restart function via 20 | #' \code{getOption("restart")}. 21 | #' 22 | #' @export 23 | disable <- function(project = NULL, restart = TRUE) { 24 | 25 | # get the project 26 | project <- getProjectDir(project) 27 | 28 | # remove packrat from the .Rprofile 29 | editRprofileAutoloader(project, "remove") 30 | 31 | # turn packrat mode off 32 | if (isPackratModeOn()) 33 | off(project) 34 | 35 | # restart if requested 36 | if (restart) 37 | attemptRestart(restore.packrat.mode = FALSE) 38 | 39 | invisible() 40 | } 41 | -------------------------------------------------------------------------------- /R/env.R: -------------------------------------------------------------------------------- 1 | # Tools for getting info about the execution environment 2 | 3 | tar_binary <- function() { 4 | # If TAR is specified in the environment, use that. 5 | tar <- Sys.getenv("TAR", unset = NA) 6 | if (!is.na(tar)) { 7 | return(tar) 8 | } 9 | 10 | # If we're on Unix, look for a tar binary on the PATH. 11 | if (is.unix()) { 12 | tar <- file.path(Sys.which("tar")) 13 | if (file.exists(tar)) { 14 | return(tar) 15 | } 16 | } 17 | 18 | # If we're on Windows, look for the system tar binary. 19 | if (is.windows()) { 20 | root <- Sys.getenv("SystemRoot", unset = NA) 21 | if (is.na(root)) { 22 | root <- "C:/Windows" 23 | } 24 | tar <- file.path(root, "System32/tar.exe") 25 | if (file.exists(tar)) { 26 | return(tar) 27 | } 28 | } 29 | 30 | # Return internal only as a fallback with a warning. 31 | warning("No external tar binary found. Using R's internal TAR, which may cause failures with long filenames.") 32 | return("internal") 33 | } 34 | 35 | # Tools for storing state in environment variables. Possibly unused. 36 | getenv <- function(x) { 37 | strsplit(Sys.getenv(x, unset = ""), .Platform$path.sep, fixed = TRUE)[[1]] 38 | } 39 | 40 | setenv <- function(...) { 41 | dots <- list(...) 42 | 43 | # validate argument length 44 | n <- length(dots) 45 | if (n %% 2 != 0) 46 | stop("expected even number of arguments to 'setenv'") 47 | 48 | # extract keys, values from '...' 49 | indices <- seq(1, length(dots), by = 2) 50 | keys <- dots[indices] 51 | vals <- dots[indices + 1] 52 | 53 | # construct call to Sys.setenv 54 | names(vals) <- keys 55 | vals <- lapply(vals, function(val) { 56 | paste(val, collapse = .Platform$path.sep) 57 | }) 58 | do.call(Sys.setenv, vals) 59 | } 60 | 61 | unsetenv <- function(name) { 62 | Sys.unsetenv(name) 63 | } 64 | -------------------------------------------------------------------------------- /R/external.R: -------------------------------------------------------------------------------- 1 | ##' Managing External Libraries 2 | ##' 3 | ##' These functions provide a mechanism for (temporarily) using packages outside 4 | ##' of the packrat private library. The packages are searched within the 'default' 5 | ##' libraries; that is, the libraries that would be available upon launching a new 6 | ##' \R session. 7 | ##' 8 | ##' @param packages An optional set of package names (as a character 9 | ##' vector) to load for the duration of evaluation of \code{expr}. 10 | ##' Whether \code{packages} is provided or \code{NULL} (the 11 | ##' default), \code{expr} is evaluated in an environment where the 12 | ##' external library path is in place, not the local (packrat) 13 | ##' library path. 14 | ##' @param expr An \R expression. 15 | ##' @param envir An environment in which the expression is evaluated. 16 | ##' @name packrat-external 17 | ##' @rdname packrat-external 18 | ##' @examples \dontrun{ 19 | ##' with_extlib("lattice", xyplot(1 ~ 1)) 20 | ##' with_extlib(expr = packageVersion("lattice")) 21 | ##' # since devtools requires roxygen2 >= 5.0.0 for this step, this 22 | ##' # should fail unless roxygen2 is available in the packrat lib.loc 23 | ##' with_extlib("devtools", load_all("path/to/project")) 24 | ##' # this method will work given roxygen2 is installed in the 25 | ##' # non-packrat lib.loc with devtools 26 | ##' with_extlib(expr = devtools::load_all("path/to/project")) 27 | ##' } 28 | ##' @export 29 | with_extlib <- function(packages = NULL, expr, envir = parent.frame()) { 30 | 31 | # need to force this promise now otherwise it will get evaluated 32 | # in the wrong context later on 33 | force(envir) 34 | 35 | if (!is.null(packages) && !is.character(packages)) { 36 | stop("'packages' should be a character vector of libraries", call. = FALSE) 37 | } 38 | 39 | call <- match.call() 40 | 41 | local({ 42 | 43 | tryCatch({ 44 | ## Record the search path, then load the libraries 45 | oldSearch <- search() 46 | 47 | libPaths <- .packrat_mutables$get("origLibPaths") 48 | oldLibPaths <- .libPaths() 49 | if (!length(libPaths)) 50 | libPaths <- getDefaultLibPaths() 51 | .libPaths(libPaths) 52 | 53 | for (package in packages) { 54 | library(package, character.only = TRUE, warn.conflicts = FALSE) 55 | } 56 | 57 | ## Evaluate the call 58 | error <- try(res <- eval(call$expr, envir = envir), silent = TRUE) 59 | 60 | ## Now, propagate the error / result 61 | if (exists("res", envir = environment(), inherits = FALSE)) { 62 | res 63 | } else { 64 | stop(attr(error, "condition")$message, call. = FALSE) 65 | } 66 | }, 67 | 68 | finally = { 69 | newSearch <- search() 70 | for (path in setdiff(newSearch, oldSearch)) { 71 | try(forceUnload(path)) 72 | } 73 | .libPaths(oldLibPaths) 74 | }) 75 | 76 | }) 77 | 78 | } 79 | 80 | ##' @name packrat-external 81 | ##' @rdname packrat-external 82 | ##' @export 83 | extlib <- function(packages) { 84 | 85 | # place user library at front of library paths (we want to 86 | # include both the user library and the packrat library just 87 | # so that external packaegs can still load and depend on 88 | # packages only installed within the private library as well) 89 | oldLibPaths <- .libPaths() 90 | newLibPaths <- c(getDefaultLibPaths(), .libPaths()) 91 | 92 | .libPaths(newLibPaths) 93 | on.exit(.libPaths(oldLibPaths), add = TRUE) 94 | 95 | for (package in packages) 96 | library(package, character.only = TRUE) 97 | 98 | } 99 | 100 | loadExternalPackages <- function() { 101 | pkgs <- get_opts("external.packages") 102 | if (length(pkgs)) { 103 | pkgs <- pkgs[!is.null(pkgs) & !is.na(pkgs) & nchar(pkgs)] 104 | failures <- dropNull(lapply(pkgs, function(pkg) { 105 | tryCatch( 106 | expr = extlib(pkg), 107 | error = function(e) { 108 | pkg 109 | } 110 | ) 111 | })) 112 | if (length(failures)) { 113 | failures <- as.character(unlist(failures)) 114 | message("Warning: failed to load the following external packages:\n- ", 115 | paste(shQuote(failures), collapse = ", ")) 116 | } 117 | return(length(failures) > 0) 118 | } 119 | return(TRUE) 120 | } 121 | -------------------------------------------------------------------------------- /R/get-package-actions.R: -------------------------------------------------------------------------------- 1 | # returns a list of actions that would be performed if the given action were 2 | # performed on the given project 3 | getActions <- function(verb, project) { 4 | project <- getProjectDir(project) 5 | if (verb == "restore") 6 | actionFunc <- restore 7 | else if (verb == "snapshot") 8 | actionFunc <- snapshot 9 | else if (verb == "clean") 10 | actionFunc <- clean 11 | else 12 | stop("Unknown action '", verb, "'") 13 | suppressMessages(actionFunc(project = project, dry.run = TRUE)) 14 | } 15 | 16 | getActionMessages <- function(verb, project) { 17 | records <- getActions(verb, project) 18 | suppressMessages(packageActionMessages(verb, records)) 19 | } 20 | 21 | packageActionMessages <- function(verb, records) { 22 | 23 | if (!length(records$actions)) { 24 | message("No ", verb, " actions to perform!") 25 | return(invisible(NULL)) 26 | } 27 | 28 | pkgNames <- names(records$actions) 29 | ip <- installed.packages() 30 | installedPkgInfo <- suppressWarnings(getInstalledPkgInfo(pkgNames, ip)) 31 | 32 | # pkgRecords 33 | # |__ . 34 | # | |__ name 35 | # | |__ source 36 | # | |__ version 37 | # | |__ source_path 38 | # | \__ depends 39 | # \__ . 40 | # |__ name 41 | # |__ source 42 | # |__ version 43 | # |__ source_path 44 | # \__ depends 45 | # actions 46 | # repos 47 | # project 48 | # targetLib 49 | 50 | parens <- function(x) { 51 | paste("(", x, ")", sep = "", collapse = ", ") 52 | } 53 | 54 | n <- length(records$actions) 55 | msgs <- data.frame( 56 | package = names(records$actions), 57 | action = unname(records$actions), 58 | packrat.version = character(n), 59 | library.version = character(n), 60 | message = character(n), 61 | stringsAsFactors = FALSE 62 | ) 63 | for (i in seq_along(records$actions)) { 64 | action <- records$actions[[i]] 65 | package <- names(records$actions)[[i]] 66 | record <- records$pkgRecords[sapply(records$pkgRecords, function(x) { 67 | x$name == package 68 | })] 69 | packrat.version <- 70 | if (length(record) == 1) 71 | record[[1]]$version 72 | else 73 | NA 74 | library.version <- installedPkgInfo[[package]][["Version"]] %||% NA 75 | if (verb == "snapshot") 76 | { 77 | msgs$message[[i]] <- 78 | switch(action, 79 | add = paste("Add", shQuote(package), parens(library.version), "to Packrat"), 80 | remove = paste("Remove", shQuote(package), parens(packrat.version), "from Packrat"), 81 | upgrade = paste("Replace", shQuote(package), parens(paste(packrat.version, "->", library.version)), "in Packrat"), 82 | downgrade = paste("Replace", shQuote(package), parens(paste(packrat.version, "->", library.version)), "in Packrat"), 83 | crossgrade = paste("Crossgrade", shQuote(package), parens(paste(packrat.version, "->", library.version)), "in Packrat"), 84 | stop("Unrecognized action") 85 | ) 86 | } 87 | else 88 | { 89 | msgs$message[[i]] <- 90 | switch(action, 91 | add = paste("Install", shQuote(package), parens(packrat.version)), 92 | remove = paste("Uninstall", shQuote(package), parens(packrat.version)), 93 | upgrade = paste("Upgrade", shQuote(package), parens(paste(library.version, "->", packrat.version))), 94 | downgrade = paste("Downgrade", shQuote(package), parens(paste(library.version, "->", packrat.version))), 95 | crossgrade = paste("Crossgrade", shQuote(package), parens(paste(library.version, "->", packrat.version))), 96 | stop("Unrecognized action") 97 | ) 98 | } 99 | msgs$packrat.version[[i]] <- packrat.version 100 | msgs$library.version[[i]] <- library.version 101 | } 102 | msgs 103 | } 104 | -------------------------------------------------------------------------------- /R/git-prune.R: -------------------------------------------------------------------------------- 1 | git_files <- function(project = NULL) { 2 | project <- getProjectDir(project) 3 | owd <- getwd() 4 | setwd(project) 5 | on.exit(setwd(owd)) 6 | objects <- system("git rev-list --all --objects", intern = TRUE) 7 | splat <- strsplit(objects, " ", fixed = TRUE) 8 | sort(unique(unlist(sapply(splat, function(x) { 9 | if (length(x) == 2) x[[2]] else NULL 10 | })))) 11 | } 12 | 13 | git_prune <- function(project = NULL, prune.lib = TRUE, prune.src = FALSE) { 14 | # See: http://stevelorek.com/how-to-shrink-a-git-repository.html for notes 15 | project <- getProjectDir(project) 16 | owd <- getwd() 17 | setwd(project) 18 | on.exit(setwd(owd)) 19 | if (!isGitProject(project)) 20 | stop("Not a git project (no .git/ directory found)", call. = FALSE) 21 | 22 | localBranches <- system("git branch", intern = TRUE) 23 | localBranches <- gsub("^[[:blank:]]*", "", localBranches) 24 | allBranches <- system("git branch -a | grep remotes | grep -v HEAD | grep -v master", 25 | intern = TRUE) 26 | allBranches <- gsub("^[[:blank:]]*", "", allBranches) 27 | needsClone <- allBranches[!(gsub(".*/", "", allBranches) %in% localBranches)] 28 | 29 | if (length(needsClone)) { 30 | message("Deep-cloning Git repository...") 31 | for (branch in needsClone) 32 | system(paste("git branch --track", 33 | gsub(".*/", "", branch), 34 | branch), ignore.stdout = TRUE, ignore.stderr = TRUE) 35 | message("Done!") 36 | } 37 | 38 | allFiles <- git_files() 39 | toRemove <- character() 40 | if (prune.lib) 41 | toRemove <- c(toRemove, grep("^packrat/lib*/", allFiles, value = TRUE)) 42 | if (prune.src) 43 | toRemove <- c(toRemove, grep("^packrat/src/", allFiles, value = TRUE)) 44 | 45 | n <- length(toRemove) 46 | if (!n) { 47 | message("Nothing to prune. Exiting...") 48 | return(invisible(character())) 49 | } 50 | 51 | for (i in seq_along(toRemove)) { 52 | file <- toRemove[[i]] 53 | message("Removing file ", i, " of ", n, "...") 54 | cmd <- paste("git filter-branch --tag-name-filter cat --index-filter", 55 | "'git rm -r --cached --ignore-unmatch", 56 | file, 57 | "' --prune-empty -f -- --all") 58 | system(cmd, ignore.stdout = TRUE, ignore.stderr = TRUE) 59 | } 60 | 61 | unlink(file.path(project, ".git", "refs", "original"), recursive = TRUE) 62 | system("git reflog expire --expire=now --all") 63 | system("git gc --prune=now") 64 | system("git gc --aggressive --prune=now") 65 | message("Done!") 66 | return(invisible(toRemove)) 67 | 68 | } 69 | -------------------------------------------------------------------------------- /R/github.R: -------------------------------------------------------------------------------- 1 | # - Equivalent to other git provider download functions. 2 | # - Called by `getSourceForPkgRecord` (which manages the lifecycle of 3 | # `destfile`). Responsible for dispatching different download implementations 4 | # depending on environment and configuration, passing them `url` and 5 | # `destfile`. 6 | # - Returns nothing if successful, and does not check the return values of inner 7 | # download methods (`renvDownload`, `githubDownloadHttr`, and 8 | # `downloadWithRetries`). Those functions are responsible for detecting errors 9 | # and calling `stop` when they occur. 10 | # - For authenticated download methods (`renvDownload`, `githubDownloadHttr`), 11 | # catches errors append a note advising the user to check 12 | # configuration-related environment variables. This happens no matter what the 13 | # cause of the error. 14 | githubDownload <- function(url, destfile, ...) { 15 | if (githubAuthenticated() && canUseRenvDownload()) { 16 | tryCatch(renvDownload(url, destfile, type = "github"), error = authDownloadAdvice("github", TRUE, "renv")) 17 | } else if (githubAuthenticated() && canUseHttr()) { 18 | tryCatch(githubDownloadHttr(url, destfile), error = authDownloadAdvice("github", TRUE, "httr")) 19 | } else { 20 | tryCatch(downloadWithRetries(url, destfile = destfile), error = authDownloadAdvice("github", FALSE, "internal")) 21 | } 22 | } 23 | 24 | # - The original function for authenticated downloads. Requires `httr` to be 25 | # installed. Called by this git provider's top-level download function if 26 | # `renvDownload`'s requirements are not met, but this function's are. 27 | # - Returns `TRUE` if it succeeds. Calls `stop()` if any errors are encountered. 28 | # - Writes to `destfile`, whose lifecycle is managed by `getSourceForPkgRecord`. 29 | githubDownloadHttr <- function(url, destfile, ...) { 30 | authenticate <- yoink("httr", "authenticate") 31 | GET <- yoink("httr", "GET") 32 | content <- yoink("httr", "content") 33 | 34 | token <- github_pat(quiet = TRUE) 35 | auth <- if (!is.null(token)) { 36 | authenticate(token, "x-oauth-basic", "basic") 37 | } else { 38 | list() 39 | } 40 | 41 | result <- GET(url, auth) 42 | if (result$status != 200) { 43 | stop(httr::http_status(result)$message) 44 | } 45 | writeBin(content(result, "raw"), destfile) 46 | if (!file.exists(destfile)) { 47 | stop("No data received.", call. = FALSE) 48 | } 49 | # Success! 50 | return(TRUE) 51 | } 52 | 53 | githubArchiveUrl <- function(pkgRecord) { 54 | # Determine what protocol we can use, preferring https. Note that 'wininet' 55 | # can fail if attempting to download from an 'http' URL that redirects to an 56 | # 'https' URL. https://github.com/rstudio/packrat/issues/269 57 | method <- tryCatch( 58 | secureDownloadMethod(), 59 | error = function(e) "internal" 60 | ) 61 | protocol <- if (identical(method, "internal")) "http" else "https" 62 | 63 | if (is.null(pkgRecord$remote_host) || !nzchar(pkgRecord$remote_host)) { 64 | # Guard against packages installed with older versions of devtools 65 | # (it's possible the associated package record will not contain a 66 | # 'remote_host' entry) 67 | fmt <- "api.github.com/repos/%s/%s/tarball/%s" 68 | archiveUrl <- sprintf(fmt, 69 | pkgRecord$gh_username, 70 | pkgRecord$gh_repo, 71 | pkgRecord$gh_sha1) 72 | } else { 73 | # Prefer using the 'remote_host' entry as it allows for successfully 74 | # installation of packages available on private GitHub repositories 75 | # (which will not use api.github.com) 76 | fmt <- "%s/repos/%s/%s/tarball/%s" 77 | archiveUrl <- sprintf(fmt, 78 | pkgRecord$remote_host, 79 | pkgRecord$remote_username, 80 | pkgRecord$remote_repo, 81 | pkgRecord$remote_sha) 82 | } 83 | 84 | # Ensure the protocol is prepended 85 | if (!grepl("^http", archiveUrl)) { 86 | archiveUrl <- paste(protocol, archiveUrl, sep = "://") 87 | } 88 | return(archiveUrl) 89 | } 90 | 91 | isGitHubURL <- function(url) { 92 | is.string(url) && grepl("^http(?:s)?://(?:www|api).github.com", url, perl = TRUE) 93 | } 94 | 95 | githubAuthenticated <- function() { 96 | !is.null(github_pat(quiet = TRUE)) 97 | } 98 | 99 | github_pat <- function(quiet = TRUE) { 100 | pat <- Sys.getenv("GITHUB_PAT") 101 | if (nzchar(pat)) { 102 | if (!quiet) { 103 | message("Using GitHub PAT from envvar GITHUB_PAT") 104 | } 105 | return(pat) 106 | } 107 | return(NULL) 108 | } 109 | -------------------------------------------------------------------------------- /R/gitlab.R: -------------------------------------------------------------------------------- 1 | 2 | # - Equivalent to other git provider download functions. 3 | # - Called by `getSourceForPkgRecord` (which manages the lifecycle of 4 | # `destfile`). Responsible for dispatching different download implementations 5 | # depending on environment and configuration, passing them `url` and 6 | # `destfile`. 7 | # - Returns nothing if successful, and does not check the return values of inner 8 | # download methods (`renvDownload`, `providerDownloadHttr`, and 9 | # `downloadWithRetries`). Those functions are responsible for detecting errors 10 | # and calling `stop` when they occur. 11 | # - For authenticated download methods (`renvDownload`, `providerDownloadHttr`), 12 | # catches errors append a note advising the user to check 13 | # configuration-related environment variables. This happens no matter what the 14 | # cause of the error. 15 | gitlabDownload <- function(url, destfile, ...) { 16 | if (gitlabAuthenticated() && canUseRenvDownload()) { 17 | tryCatch(renvDownload(url, destfile, type = "gitlab"), error = authDownloadAdvice("gitlab", TRUE, "renv")) 18 | } else if (gitlabAuthenticated() && canUseHttr()) { 19 | tryCatch(gitlabDownloadHttr(url, destfile), error = authDownloadAdvice("gitlab", TRUE, "httr")) 20 | } else { 21 | tryCatch(downloadWithRetries(url, destfile = destfile), error = authDownloadAdvice("gitlab", FALSE, "internal")) 22 | } 23 | } 24 | 25 | # - The original function for authenticated downloads. Requires `httr` to be 26 | # installed. Called by this git provider's top-level download function if 27 | # `renvDownload`'s requirements are not met, but this function's are. 28 | # - Returns `TRUE` if it succeeds. Calls `stop()` if any errors are encountered. 29 | # - Writes to `destfile`, whose lifecycle is managed by `getSourceForPkgRecord`. 30 | gitlabDownloadHttr <- function(url, destfile, ...) { 31 | authenticate <- yoink("httr", "authenticate") 32 | add_headers <- yoink("httr", "add_headers") 33 | GET <- yoink("httr", "GET") 34 | content <- yoink("httr", "content") 35 | 36 | token <- gitlab_pat(quiet = TRUE) 37 | 38 | auth <- if (!is.null(token)) { 39 | add_headers("Private-Token" = token) 40 | } else { 41 | list() 42 | } 43 | 44 | result <- GET(url, auth) 45 | if (result$status != 200) { 46 | stop(httr::http_status(result)$message) 47 | } 48 | writeBin(content(result, "raw"), destfile) 49 | if (!file.exists(destfile)) { 50 | stop("No data received.", call. = FALSE) 51 | } 52 | # Success! 53 | return(TRUE) 54 | } 55 | 56 | gitlabArchiveUrl <- function(pkgRecord) { 57 | # Determine what protocol we can use, preferring https. Note that 'wininet' 58 | # can fail if attempting to download from an 'http' URL that redirects to an 59 | # 'https' URL. https://github.com/rstudio/packrat/issues/269 60 | method <- tryCatch( 61 | secureDownloadMethod(), 62 | error = function(e) "internal" 63 | ) 64 | protocol <- if (identical(method, "internal")) "http" else "https" 65 | 66 | # If remote_host is empty, set it. 67 | if (is.null(pkgRecord$remote_host) || !nzchar(pkgRecord$remote_host)) { 68 | pkgRecord$remote_host <- "gitlab.com" 69 | } 70 | 71 | fmt <- "%s/api/v4/projects/%s/repository/archive?sha=%s" 72 | archiveUrl <- sprintf(fmt, 73 | pkgRecord$remote_host, 74 | URLencode(paste0(pkgRecord$remote_username, "/", pkgRecord$remote_repo), reserved = TRUE), 75 | pkgRecord$remote_sha) 76 | 77 | protocol <- if (identical(method, "internal")) "http" else "https" 78 | if (!grepl("^http", archiveUrl)) { 79 | archiveUrl <- paste(protocol, archiveUrl, sep = "://") 80 | } 81 | return(archiveUrl) 82 | } 83 | 84 | isGitlabURL <- function(url) { 85 | is.string(url) && grepl("^http(?:s)?://(?:www|api).gitlab.(org|com)", url, perl = TRUE) 86 | } 87 | 88 | gitlabAuthenticated <- function() { 89 | !is.null(gitlab_pat(quiet = TRUE)) 90 | } 91 | 92 | gitlab_pat <- function(quiet = TRUE) { 93 | token <- Sys.getenv("GITLAB_PAT") 94 | if (nzchar(token)) { 95 | if (!quiet) { 96 | message("Using GitLab PAT from envvar GITLAB_PAT") 97 | } 98 | return(token) 99 | } 100 | return(NULL) 101 | } 102 | -------------------------------------------------------------------------------- /R/hide-site-libraries.R: -------------------------------------------------------------------------------- 1 | replaceLibrary <- function(lib, value) { 2 | 3 | ## Need to clobber in package:base, namespace:base 4 | envs <- c( 5 | as.environment("package:base"), 6 | .BaseNamespaceEnv 7 | ) 8 | 9 | for (env in envs) { 10 | do.call("unlockBinding", list(lib, env)) 11 | assign(lib, value, envir = env) 12 | do.call("lockBinding", list(lib, env)) 13 | } 14 | 15 | } 16 | 17 | 18 | hideLibrary <- function(lib) { 19 | replaceLibrary(lib, character()) 20 | } 21 | 22 | restoreLibrary <- function(lib) { 23 | 24 | cachedLib <- if (lib == ".Library") 25 | getenv("R_PACKRAT_SYSTEM_LIBRARY") 26 | else if (lib == ".Library.site") 27 | getenv("R_PACKRAT_SITE_LIBRARY") 28 | 29 | if (is.null(cachedLib)) { 30 | warning("packrat did not properly save the library state; cannot restore") 31 | return(invisible(NULL)) 32 | } 33 | 34 | replaceLibrary(lib, cachedLib) 35 | 36 | } 37 | 38 | ## Remove the site-library libraries from unix-alikes 39 | hideSiteLibraries <- function() { 40 | hideLibrary(".Library.site") 41 | } 42 | 43 | ## Restore the site-library libraries 44 | restoreSiteLibraries <- function() { 45 | restoreLibrary(".Library.site") 46 | } 47 | -------------------------------------------------------------------------------- /R/hooks.R: -------------------------------------------------------------------------------- 1 | # Hooks for library modifying functions that can be used to auto.snapshot 2 | # and also maintain library state consistency when within packrat mode 3 | snapshotHook <- function(expr, value, ok, visible) { 4 | 5 | tryCatch( 6 | 7 | expr = { 8 | snapshotHookImpl() 9 | }, 10 | 11 | # Cases where an automatic snapshot can fail: 12 | # 13 | # 1. A library is deleted, e.g. with remove.packages. 14 | # TODO: How should we handle an automatic snapshot fail? 15 | error = function(e) { 16 | 17 | project <- .packrat_mutables$get("project") 18 | 19 | if (is.null(project)) { 20 | file <- "" ## to stdout 21 | } else { 22 | file <- file.path(project, "packrat", "packrat.log") 23 | } 24 | 25 | if (inherits(e, "simpleError")) { 26 | msg <- e$message 27 | } else { 28 | msg <- e 29 | } 30 | 31 | if (identical(file, "")) 32 | message(paste("Error on automatic snapshot:", msg)) 33 | else 34 | cat(msg, file = file, append = TRUE) 35 | } 36 | 37 | ) 38 | 39 | } 40 | 41 | ## Make a call that copies the local available.packages() cache 42 | makeCopyAvailablePackagesCacheCmd <- function(contrib.url, dir) { 43 | 44 | makeName <- function(contrib.url) { 45 | vapply(contrib.url, function(x) { 46 | paste0("repos_", URLencode(x, TRUE), ".rds") 47 | }, character(1), USE.NAMES = FALSE) 48 | } 49 | 50 | name <- makeName(contrib.url) 51 | 52 | fromCmd <- paste0("file.path(", 53 | paste(sep = ", ", 54 | surround(dir, with = "'"), 55 | surround(name, with = "'") 56 | ), 57 | ")" 58 | ) 59 | toCmd <- paste0("file.path(tempdir(), '", name, "')") 60 | 61 | paste0("file.copy(", fromCmd, ", ", toCmd, ")") 62 | } 63 | 64 | ## Builds a call that can be executed asynchronously -- returned as a character 65 | ## vector that can be pasted with e.g. paste(call, collapse = "; ") 66 | buildSnapshotHookCall <- function(project, debug = FALSE) { 67 | 68 | project <- getProjectDir() 69 | packratDir <- getPackratDir(project) 70 | snapshotLockPath <- file.path(packratDir, "snapshot.lock") 71 | 72 | ## utility paster 73 | peq <- function(x, y) paste(x, y, sep = " = ") 74 | 75 | snapshotArgs <- paste(sep = ", ", 76 | peq("project", surround(project, with = "'")), 77 | peq("auto.snapshot", "TRUE"), 78 | peq("verbose", "FALSE") 79 | ) 80 | 81 | repos <- gsub("\"", "'", paste(deparse(getOption('repos'), width.cutoff = 500), collapse = ' ')) 82 | 83 | setwdCmd <- paste0("setwd(", surround(project, with = "'"), ")") 84 | reposCmd <- paste0("options('repos' = ", repos, ")") 85 | copyAvailablePackagesCacheCmd <- makeCopyAvailablePackagesCacheCmd( 86 | contrib.url(getOption('repos')), tempdir() 87 | ) 88 | setLibsCmd <- paste0(".libPaths(c(", 89 | paste(surround(getUserLibPaths(), with = "'"), collapse = ", "), 90 | "))") 91 | if (debug) { 92 | snapshotCmd <- paste0("packrat:::snapshotImpl(", snapshotArgs, ")") 93 | } else { 94 | snapshotCmd <- paste0("try(suppressMessages(packrat:::snapshotImpl(", snapshotArgs, ")), silent = TRUE)") 95 | } 96 | cleanupCmd <- paste0("if (file.exists(", 97 | surround(snapshotLockPath, with = "'"), 98 | ")) file.remove(", 99 | surround(snapshotLockPath, with = "'"), 100 | ")") 101 | removeTmpdirCmd <- paste0("unlink(tempdir(), recursive = TRUE)") 102 | 103 | c( 104 | setwdCmd, 105 | reposCmd, 106 | copyAvailablePackagesCacheCmd, 107 | setLibsCmd, 108 | snapshotCmd, 109 | cleanupCmd, 110 | removeTmpdirCmd, 111 | "invisible()" 112 | ) 113 | } 114 | 115 | snapshotHookImpl <- function(debug = FALSE) { 116 | 117 | if (!isPackratModeOn()) return(invisible(TRUE)) 118 | if (!debug && !isTRUE(get_opts("auto.snapshot"))) 119 | return(invisible(TRUE)) 120 | project <- getProjectDir() 121 | packratDir <- getPackratDir(project) 122 | 123 | ## A snapshot lock file that we should check to ensure we don't try to 124 | ## snapshot multiple times 125 | snapshotLockPath <- file.path(packratDir, "snapshot.lock") 126 | 127 | ## This file needs to be checked, and deleted, by the async process 128 | if (file.exists(snapshotLockPath)) { 129 | ## we assume another process is currently performing an async snapshot 130 | if (debug) 131 | cat("Automatic snapshot already in process; exiting\n") 132 | return(TRUE) 133 | } 134 | 135 | fullCmd <- paste(buildSnapshotHookCall(project, debug = debug), collapse = "; ") 136 | file.create(snapshotLockPath, recursive = TRUE) 137 | r_path <- file.path(R.home("bin"), "R") 138 | args <- paste("--vanilla", "-s", "-e", surround(fullCmd, with = "\"")) 139 | if (debug) { 140 | cat("Performing an automatic snapshot:\n\n") 141 | cat(paste(surround(r_path, with = "\""), args), "\n") 142 | result <- system2(r_path, args, stdout = TRUE, stderr = TRUE) 143 | cat("Captured result:\n") 144 | print(result) 145 | } else { 146 | result <- system2(r_path, args, stdout = FALSE, stderr = FALSE, wait = FALSE) 147 | } 148 | invisible(TRUE) 149 | } 150 | -------------------------------------------------------------------------------- /R/install-local.R: -------------------------------------------------------------------------------- 1 | findPackageDirectoriesAndTarballs <- function(dir) { 2 | dirs <- list.dirs(dir, recursive = FALSE) 3 | hasDesc <- unlist(lapply(dirs, function(dir) { 4 | file.exists(file.path(dir, "DESCRIPTION")) 5 | })) 6 | dirs[hasDesc] 7 | } 8 | 9 | ##' Install a Package from a Local Repository 10 | ##' 11 | ##' This function can be used to install a package from a local 'repository'; i.e., 12 | ##' a directory containing package tarballs and sources. 13 | ##' 14 | ##' @param pkgs A character vector of package names. 15 | ##' @param lib The library in which the package should be installed. 16 | ##' @param repos The local repositories to search for the package names specified. 17 | ##' @param ... Optional arguments passed to \code{\link[packrat]{install}}. 18 | ##' @export 19 | install_local <- function(pkgs, 20 | ..., 21 | lib = .libPaths()[1], 22 | repos = get_opts("local.repos")) { 23 | for (pkg in pkgs) { 24 | install_local_single(pkg, lib = lib, repos = repos, ...) 25 | } 26 | } 27 | 28 | findLocalRepoForPkg <- function(pkg, 29 | repos = get_opts("local.repos"), 30 | fatal = TRUE) { 31 | if (!length(repos) || identical(repos, "")) return(character()) 32 | # Search through the local repositories for a suitable package 33 | hasPackage <- unlist(lapply(repos, function(repo) { 34 | file.exists(file.path(repo, pkg)) 35 | })) 36 | names(hasPackage) <- repos 37 | numFound <- sum(hasPackage) 38 | if (numFound == 0) { 39 | if (fatal) { 40 | stop("No package '", pkg, "' found in local repositories specified") 41 | } else { 42 | return(NULL) 43 | } 44 | } 45 | 46 | if (numFound > 1) 47 | warning("Package '", pkg, "' found in multiple local repositories:\n- ", 48 | paste(shQuote(file.path(repos[hasPackage], pkg)), collapse = ", ")) 49 | 50 | repos[hasPackage][1] 51 | 52 | } 53 | 54 | install_local_single <- function(pkg, 55 | lib = .libPaths()[1], 56 | repos = get_opts("local.repos"), 57 | fatal = TRUE, 58 | ...) { 59 | 60 | if (!length(repos) || identical(repos, "")) 61 | stop("No local repositories have been defined. ", 62 | "Use 'packrat::set_opts(local.repos = ...)' to add local repositories.", 63 | call. = FALSE) 64 | repoToUse <- findLocalRepoForPkg(pkg, repos, fatal = fatal) 65 | path <- file.path(repoToUse, pkg) 66 | with_libpaths(lib, install_local_path(path = path, ...)) 67 | 68 | } 69 | -------------------------------------------------------------------------------- /R/lockfile-metadata.R: -------------------------------------------------------------------------------- 1 | #' Get / Set packrat lockfile metadata 2 | #' 3 | #' Get and set metadata in the current packrat-managed project lockfile \code{packrat.lock} 4 | #' 5 | #' Project's \code{packrat.lock} contains some metadata before packages 6 | #' dependencies informations. The project's lockfile is created and updated 7 | #' programmatically by \code{\link{snapshot}}. However it could be necessary sometimes to 8 | #' modify manually some of those values. For example, it could be useful to set another repository 9 | #' CRAN url when deploying to a offline environnement. 10 | #' 11 | #' @section available metadata : 12 | #' 13 | #' \itemize{ 14 | #' \item \code{r_version}: R version the project depends on 15 | #' \item \code{repos}: Name of repos and their url recorded packages can be 16 | #' retrieve from. Only url is recommended to change if need. Name of repos is 17 | #' used in package records and must be identical 18 | #' } 19 | #' 20 | #' @param repos A named character vector of the form \code{c( = "")}. 21 | #' @param r_version A length-one character vector with suitable numeric version 22 | #' string. See \code{\link[base]{package_version}}. 23 | #' @param project The project directory. When in packrat mode, defaults to the current project; 24 | #' otherwise, defaults to the current working directory. 25 | #' @export 26 | #' @rdname lockfile-metadata 27 | #' @name lockfile-metadata 28 | #' @examples \dontrun{ 29 | #' # changes repos url 30 | #' repos <- old_repos <- get_lockfile_metadata("repos") 31 | #' repos 32 | #' repos["CRAN"] <- "https://cran.r-project.org/" 33 | #' set_lockfile_metadata(repos = repos) 34 | #' get_lockfile_metadata("repos") 35 | #' # setting back old state 36 | #' # set_lockfile_metadata(repos = old_repos) 37 | #' 38 | #' # changes R version 39 | #' rver <- old_rver <- get_lockfile_metadata("r_version") 40 | #' rver 41 | #' rver <- "3.4.1" 42 | #' set_lockfile_metadata(r_version = rver) 43 | #' get_lockfile_metadata("r_version") 44 | #' # Setting back old state 45 | #' # set_lockfile_metadata(r_version = old_rver) 46 | #' } 47 | set_lockfile_metadata <- function(repos = NULL, r_version = NULL, project = NULL) { 48 | project <- getProjectDir(project) 49 | lf_filepath <- lockFilePath(project) 50 | if (!file.exists(lf_filepath)) { 51 | stop(paste(lockFilePath, " is missing. Run packrat::init('", 52 | project, "') to generate it.", sep = "")) 53 | } 54 | lf <- as.data.frame(readDcf(lf_filepath), stringsAsFactors = FALSE) 55 | 56 | # update repos 57 | if (!is.null(repos)) { 58 | # Windows automatically transforms \n to \r\n on write through write.dcf 59 | separator <- ",\n" 60 | reposString <- paste(names(repos), unname(repos), sep = "=", collapse = separator) 61 | lf[1, "Repos"] <- reposString 62 | } 63 | 64 | # update rversion 65 | if (!is.null(r_version)) { 66 | if (length(r_version) > 1) { 67 | stop("RVersion metadata must contains one element only", call. = FALSE) 68 | } 69 | lf[1, "RVersion"] <- as.character(package_version(r_version)) 70 | } 71 | # write back the lockfile 72 | write_dcf(lf, lf_filepath) 73 | invisible() 74 | } 75 | 76 | #' @param metadata The lockfile field name(s) to draw from. 77 | #' @param simplify Boolean; if \code{TRUE} the returned metadata will be un-listed. 78 | #' 79 | #' @rdname lockfile-metadata 80 | #' @name lockfile-metadata 81 | #' @export 82 | get_lockfile_metadata <- function(metadata = NULL, simplify = TRUE, project = NULL) { 83 | project <- getProjectDir(project) 84 | # Get and parse the lockfile 85 | lockFilePath <- lockFilePath(project) 86 | if (!file.exists(lockFilePath)) { 87 | stop(paste(lockFilePath, " is missing. Run packrat::init('", 88 | project, "') to generate it.", sep = "")) 89 | } 90 | lf_metadata <- readLockFile(lockFilePath)[names(available_metadata)] 91 | if (is.null(metadata)) { 92 | lf_metadata 93 | } else { 94 | result <- lf_metadata[names(lf_metadata) %in% metadata] 95 | if (simplify) unlist(unname(result)) 96 | else result 97 | } 98 | } 99 | 100 | # lockfile metadata available for modification and r_aliases 101 | available_metadata <- c( 102 | r_version = "RVersion", 103 | repos = "Repos" 104 | ) 105 | -------------------------------------------------------------------------------- /R/package-namespace-helpers.R: -------------------------------------------------------------------------------- 1 | loaded_user_pkgs <- function() { 2 | loaded <- loadedNamespaces() 3 | ip <- installed.packages() 4 | basePkgs <- rownames(ip)[!is.na(ip[, "Priority"])] 5 | loaded[!(loaded %in% basePkgs)] 6 | } 7 | 8 | ns_imports <- function(packages) { 9 | setNames(lapply(packages, ns_imports_single), packages) 10 | } 11 | 12 | ns_imports_single <- function(package) { 13 | ns <- asNamespace(package) 14 | names(getNamespaceImports(ns)) 15 | } 16 | 17 | is_imported <- function(package) { 18 | imports <- ns_imports(loadedNamespaces()) 19 | any(sapply(imports, function(x) package %in% x)) 20 | } 21 | 22 | unloadable <- function(packages) { 23 | result <- sapply(packages, Negate(is_imported)) 24 | names(result)[result] 25 | } 26 | -------------------------------------------------------------------------------- /R/platform.R: -------------------------------------------------------------------------------- 1 | is.windows <- function() { 2 | .Platform$OS.type == "windows" 3 | } 4 | 5 | is.unix <- function() { 6 | .Platform$OS.type == "unix" 7 | } 8 | 9 | is.mac <- function() { 10 | Sys.info()["sysname"] == "Darwin" 11 | } 12 | 13 | is.linux <- function() { 14 | Sys.info()["sysname"] == "Linux" 15 | } 16 | -------------------------------------------------------------------------------- /R/pretty-print.R: -------------------------------------------------------------------------------- 1 | ## Pretty printers, primarily used for status output 2 | prettyPrint <- function(packages, header, footer = NULL) { 3 | if (length(packages) > 0) { 4 | cat('\n') 5 | if (!is.null(header)) { 6 | cat(paste(header, collapse = '')) 7 | cat('\n') 8 | } 9 | print.simple.list(lapply(packages, function(pkg) { 10 | result <- ifelse(is.na(pkg$version), '', pkg$version) 11 | result <- paste(" ", result) 12 | names(result) <- paste(" ", pkg$name) 13 | result 14 | })) 15 | if (!is.null(footer)) { 16 | cat('\n') 17 | cat(paste(footer, collapse = '')) 18 | } 19 | cat('\n') 20 | } 21 | } 22 | 23 | summarizeDiffs <- function(diffs, pkgsA, pkgsB, addMessage, 24 | removeMessage, upgradeMessage, downgradeMessage, 25 | crossgradeMessage) 26 | { 27 | prettyPrint( 28 | searchPackages(pkgsB, names(diffs)[!is.na(diffs) & diffs == 'add']), 29 | addMessage 30 | ) 31 | prettyPrint( 32 | searchPackages(pkgsA, names(diffs)[!is.na(diffs) & diffs == 'remove']), 33 | removeMessage 34 | ) 35 | prettyPrintPair( 36 | searchPackages(pkgsA, names(diffs)[!is.na(diffs) & diffs == 'upgrade']), 37 | searchPackages(pkgsB, names(diffs)[!is.na(diffs) & diffs == 'upgrade']), 38 | upgradeMessage 39 | ) 40 | prettyPrintPair( 41 | searchPackages(pkgsA, names(diffs)[!is.na(diffs) & diffs == 'downgrade']), 42 | searchPackages(pkgsB, names(diffs)[!is.na(diffs) & diffs == 'downgrade']), 43 | downgradeMessage 44 | ) 45 | prettyPrintPair( 46 | searchPackages(pkgsA, names(diffs)[!is.na(diffs) & diffs == 'crossgrade']), 47 | searchPackages(pkgsB, names(diffs)[!is.na(diffs) & diffs == 'crossgrade']), 48 | crossgradeMessage 49 | ) 50 | } 51 | 52 | prettyPrintPair <- function(packagesFrom, packagesTo, header, footer = NULL, 53 | fromLabel = 'from', toLabel = 'to') { 54 | 55 | if (length(packagesFrom) != length(packagesTo)) { 56 | stop('Invalid arguments--package record lengths mismatch') 57 | } 58 | 59 | if (length(packagesFrom) > 0) { 60 | if (any(sapply(packagesFrom, is.null) & sapply(packagesTo, is.null))) { 61 | stop('Invalid arguments--NULL packages') 62 | } 63 | for (i in seq_along(packagesFrom)) { 64 | if (!is.null(packagesFrom[[i]]) && !is.null(packagesTo[[i]])) { 65 | if (!identical(packagesFrom[[i]]$name, packagesTo[[i]]$name)) { 66 | stop('Invalid arguments--package names did not match') 67 | } 68 | } 69 | } 70 | 71 | cat('\n') 72 | if (!is.null(header)) { 73 | cat(paste(header, collapse = '')) 74 | cat('\n') 75 | } 76 | 77 | pickVersion <- pick("version", defaultValue = "NA") 78 | df <- data.frame(paste(" ", sapply(packagesFrom, pickVersion)), 79 | paste(" ", sapply(packagesTo, pickVersion))) 80 | names(df) <- c(paste(" ", fromLabel), paste(" ", toLabel)) 81 | row.names(df) <- paste(" ", pkgNames(packagesFrom)) 82 | print(df) 83 | 84 | if (!is.null(footer)) { 85 | cat('\n') 86 | cat(paste(footer, collapse = '')) 87 | } 88 | cat('\n') 89 | } 90 | } 91 | 92 | prettyPrintNames <- function(packageNames, header, footer = NULL) { 93 | if (length(packageNames) > 0) { 94 | cat('\n') 95 | if (!is.null(header)) { 96 | cat(paste(header, collapse = '')) 97 | cat('\n') 98 | } 99 | cat(paste(" ", packageNames, sep = '', collapse = '\n')) 100 | cat('\n') 101 | if (!is.null(footer)) { 102 | cat(paste(footer, collapse = '')) 103 | } 104 | cat('\n') 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /R/r-hooks.R: -------------------------------------------------------------------------------- 1 | # Call an action hook (indicating whether the action is running or not) 2 | callHook <- function(project, action, running) { 3 | project <- normalizePath(project, winslash = '/') 4 | for (fun in getHooksList("packrat.onAction")) { 5 | if (is.character(fun)) 6 | fun <- get(fun) 7 | try(fun(project, action, running)) 8 | } 9 | } 10 | 11 | # The value for getHook can be a single function or a list of functions, 12 | # This function ensures that the result can always be processed as a list 13 | getHooksList <- function(name) { 14 | hooks <- getHook(name) 15 | if (!is.list(hooks)) 16 | hooks <- list(hooks) 17 | hooks 18 | } 19 | -------------------------------------------------------------------------------- /R/read-lock-file.R: -------------------------------------------------------------------------------- 1 | # Read only package entries in the lock file, and do not expand package dependencies 2 | # Useful when a package + its requirements is of interest, and expansion of 3 | # sub-dependencies is unnecessary 4 | readLockFilePackages <- function(file) { 5 | 6 | # Drop the first row as it contains lockfile-specific info 7 | lock <- readDcf(file)[-1, , drop = FALSE] 8 | result <- apply(lock, 1, function(x) { 9 | x <- as.list(x) 10 | list( 11 | name = x$Package, 12 | source = x$Source, 13 | version = x$Version, 14 | requires = as.character(unlist(strsplit(as.character(x$Requires), ",[[:space:]]*", perl = TRUE))), 15 | hash = x$Hash 16 | ) 17 | }) 18 | names(result) <- lock[, "Package"] 19 | result 20 | 21 | } 22 | -------------------------------------------------------------------------------- /R/remote-info.R: -------------------------------------------------------------------------------- 1 | # This code is difficult to read and has caused problems in the past. Heed my 2 | # warning. This so that as.data.frame() is given a list. The *_subdir fields are 3 | # missing in most cases. If they were included in the main list() calls, list() 4 | # would include a field with that name with a NULL value. 5 | # 6 | # Creating a list and then concatenating the possibly-NULL subdir fields means 7 | # that they are NULL, they will not appear at all in the resulting list at all. 8 | # The resulting data frame is later appended to the DESCRIPTION file, so this is 9 | # desirable. 10 | getRemoteInfo <- function(pkgRecord) { 11 | if (pkgRecord$source == "github") { 12 | return( 13 | as.data.frame(as.list(c( 14 | RemoteType = pkgRecord$source, 15 | GithubRepo = pkgRecord$gh_repo, 16 | GithubUsername = pkgRecord$gh_username, 17 | GithubRef = pkgRecord$gh_ref, 18 | GithubSHA1 = pkgRecord$gh_sha1, 19 | GithubSubdir = pkgRecord$gh_subdir 20 | )), stringsAsFactors = FALSE) 21 | ) 22 | } else { 23 | return( 24 | as.data.frame(as.list(c( 25 | RemoteType = pkgRecord$source, 26 | RemoteHost = pkgRecord$remote_host, 27 | RemoteRepo = pkgRecord$remote_repo, 28 | RemoteUsername = pkgRecord$remote_username, 29 | RemoteRef = pkgRecord$remote_ref, 30 | RemoteSha = pkgRecord$remote_sha, 31 | RemoteSubdir = pkgRecord$remote_subdir 32 | )), stringsAsFactors = FALSE) 33 | ) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /R/renv.R: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # renv 1.0.3.9000 [rstudio/renv#1f5bafc]: A dependency management toolkit for R. 4 | # Generated using `renv:::vendor()` at 2023-10-18 14:18:45.514687. 5 | # 6 | 7 | 8 | renv <- new.env(parent = new.env()) 9 | 10 | renv$initialize <- function() { 11 | 12 | # set up renv + imports environments 13 | attr(renv, "name") <- "embedded:renv" 14 | attr(parent.env(renv), "name") <- "imports:renv" 15 | 16 | # get imports 17 | imports <- list( 18 | tools = c( 19 | "file_ext", 20 | "pskill", 21 | "psnice", 22 | "write_PACKAGES" 23 | ), 24 | utils = c( 25 | "Rprof", 26 | "URLencode", 27 | "adist", 28 | "available.packages", 29 | "browseURL", 30 | "citation", 31 | "contrib.url", 32 | "download.file", 33 | "download.packages", 34 | "file.edit", 35 | "getCRANmirrors", 36 | "head", 37 | "help", 38 | "install.packages", 39 | "installed.packages", 40 | "modifyList", 41 | "old.packages", 42 | "packageDescription", 43 | "packageVersion", 44 | "read.table", 45 | "remove.packages", 46 | "sessionInfo", 47 | "str", 48 | "summaryRprof", 49 | "tail", 50 | "tar", 51 | "toBibtex", 52 | "untar", 53 | "unzip", 54 | "update.packages", 55 | "zip" 56 | ) 57 | ) 58 | 59 | # load the imports required by renv 60 | for (package in names(imports)) { 61 | namespace <- asNamespace(package) 62 | functions <- imports[[package]] 63 | list2env(mget(functions, envir = namespace), envir = parent.env(renv)) 64 | } 65 | 66 | # source renv into the aforementioned environment 67 | script <- system.file("vendor/renv.R", package = .packageName) 68 | sys.source(script, envir = renv) 69 | 70 | # initialize metadata 71 | renv$the$metadata <- list( 72 | embedded = TRUE, 73 | version = structure("1.0.3.9000", sha = "1f5bafc05a09ce6b30b83b835ffcd70547fe4fae") 74 | ) 75 | 76 | # run our load / attach hooks so internal state is initialized 77 | renv$renv_zzz_load() 78 | 79 | # remove our initialize method when we're done 80 | rm(list = "initialize", envir = renv) 81 | 82 | } 83 | -------------------------------------------------------------------------------- /R/rstudio-protocol.R: -------------------------------------------------------------------------------- 1 | # This package contains methods invoked by the RStudio IDE. If a breaking change 2 | # is made to the signature or behavior of these methods, bump this version to 3 | # prevent older versions of RStudio from attempting integration. 4 | # 5 | # Note that: 6 | # - RStudio uses the version number of the package to determine if the package 7 | # meets the minimum version requirement for integration (is the package too 8 | # old?), and this protocol number to determine the maximum version requirement 9 | # (is it too new?). 10 | # - Backwards compatibility is presumed: that is, if RStudio has protocol 3 and 11 | # the package has protocol 2, it is accepted. The package version number, not 12 | # the protocol version number, is used to determine whether the package is too 13 | # old to be compatible. 14 | 15 | .RStudio_protocol_version <- 1 16 | -------------------------------------------------------------------------------- /R/search-path.R: -------------------------------------------------------------------------------- 1 | ##' Get Packages on the Search Path 2 | ##' 3 | ##' Retrieve the packages on the search path, as well as the 4 | ##' associated library location. 5 | ##' 6 | ##' @export 7 | search_path <- function() { 8 | 9 | ## NOTE: We cannot use searchpaths() here because it follows symlinks -- 10 | ## for consistency, we want to use the symlink, not the actual path 11 | 12 | ## Start by getting everything on the search path + the library location 13 | pkgs <- data.frame( 14 | package = search(), 15 | stringsAsFactors = FALSE 16 | ) 17 | 18 | ## Filter to only actual packages 19 | pkgs <- pkgs[grep("^package:", pkgs$package), , drop = FALSE] 20 | 21 | ## Clean up the package name by removing the initial 'package:' 22 | pkgs$package <- sub("^package:", "", pkgs$package) 23 | 24 | ## Get the library locations 25 | ## NOTE: find.package is special-cased when the first argument is 26 | ## of length 1 -- we rely on that behaviour here 27 | ## normalizePath used on Windows because .Library can be stored as a 28 | ## truncated path 29 | ## ...but only do it on Windows, because normalizePath will resolve symlinks, 30 | ## which we want to avoid here 31 | pkgs$lib.loc <- unlist(lapply(pkgs$package, find.package)) 32 | if (is.windows()) { 33 | pkgs$lib.loc <- normalizePath(pkgs$lib.loc, winslash = "/") 34 | } 35 | 36 | ## Get just the directory containing the library, not the library path itself 37 | pkgs$lib.dir <- dirname(pkgs$lib.loc) 38 | 39 | ## Arrange by lib.dir 40 | pkgs <- pkgs[order(pkgs$lib.dir), ] 41 | 42 | ## Unset the rownames 43 | rownames(pkgs) <- NULL 44 | 45 | pkgs 46 | 47 | } 48 | -------------------------------------------------------------------------------- /R/update.R: -------------------------------------------------------------------------------- 1 | updateInit <- function() { 2 | 3 | # Update init.R (the file sourced from within the .Rprofile) 4 | init.R <- readLines(file.path("inst", "resources", "init.R")) 5 | packrat.version <- read.dcf("DESCRIPTION")[1, "Version"] 6 | 7 | ## Sync the packrat path, messages 8 | source("R/aaa-globals.R") 9 | 10 | installAgentLine <- grep("## -- InstallAgent -- ##", init.R) 11 | init.R[installAgentLine + 1] <- paste(" installAgent <-", shQuote(paste("InstallAgent:", "packrat", packrat.version), type = "cmd")) 12 | 13 | installSourceLine <- grep("## -- InstallSource -- ##", init.R) 14 | init.R[installSourceLine + 1] <- paste(" installSource <-", shQuote(paste("InstallSource:", "source"), type = "cmd")) 15 | 16 | cat(init.R, file = file.path("inst", "resources", "init.R"), sep = "\n") 17 | 18 | # Update the .Rprofile that is written out to a project directory 19 | .Rprofile <- readLines(file.path("inst", "resources", "init-rprofile.R")) 20 | version <- read.dcf("DESCRIPTION")[, "Version"] 21 | .Rprofile[1] <- paste0("#### -- Packrat Autoloader (version ", version, ") -- ####") 22 | cat(.Rprofile, file = file.path("inst", "resources", "init-rprofile.R"), sep = "\n") 23 | } 24 | 25 | # This function is used to update project settings, typically called after 26 | # a call to packrat::set_opts 27 | updateSettings <- function(project = NULL, options = NULL) { 28 | 29 | project <- getProjectDir(project) 30 | 31 | if (is.null(options)) { 32 | options <- get_opts(project = project) 33 | } 34 | 35 | # Make sure the packrat directory is ignored if we're in a package 36 | if (file.exists(file.path(project, "DESCRIPTION"))) { 37 | updateRBuildIgnore(project) 38 | } 39 | 40 | if (isGitProject(project)) { 41 | updateGitIgnore(project, options) 42 | } 43 | 44 | if (isSvnProject(project)) { 45 | updateSvnIgnore(project, options) 46 | } 47 | 48 | # Set the repositories 49 | if (file.exists(lockFilePath(project))) { 50 | lockFile <- readLockFile(file = lockFilePath(project)) 51 | options('repos' = lockFile$repos) 52 | } 53 | 54 | # Update the external packages library 55 | symlinkExternalPackages(project = project) 56 | 57 | invisible(TRUE) 58 | 59 | } 60 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | 3 | mappings <- list( 4 | "R_PACKRAT_DEFAULT_LIBPATHS" = .libPaths(), 5 | "R_PACKRAT_SYSTEM_LIBRARY" = .Library, 6 | "R_PACKRAT_SITE_LIBRARY" = .Library.site 7 | ) 8 | 9 | enumerate(mappings, function(key, val) { 10 | if (is.na(Sys.getenv(key, unset = NA))) 11 | setenv(key, val) 12 | }) 13 | 14 | renv$initialize() 15 | 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![R-CMD-check](https://github.com/rstudio/packrat/workflows/R-CMD-check/badge.svg)](https://github.com/rstudio/packrat/actions) 4 | 5 | 6 | ## NOTE 7 | 8 | Packrat has been soft-deprecated and is now superseded by 9 | [renv](https://github.com/rstudio/renv). 10 | 11 | While we will continue maintaining Packrat, all new development will focus on 12 | `renv`. If you're interested in switching to `renv`, you can use 13 | `renv::migrate()` to migrate a project from Packrat to `renv`. 14 | 15 | --- 16 | 17 | # packrat 18 | 19 | Packrat is a dependency management system for R. 20 | 21 | Use packrat to make your R projects more: 22 | 23 | * **Isolated:** Installing a new or updated package for one project won't break 24 | your other projects, and vice versa. That's because packrat gives each 25 | project its own private package library. 26 | * **Portable:** Easily transport your projects from one computer to another, 27 | even across different platforms. Packrat makes it easy to install the 28 | packages your project depends on. 29 | * **Reproducible:** Packrat records the exact package versions you depend on, 30 | and ensures those exact versions are the ones that get installed wherever you 31 | go. 32 | 33 | See the [project page](https://rstudio.github.io/packrat/) for more information, 34 | or join the discussion on the 35 | [RStudio Community forums](https://community.rstudio.com). 36 | 37 | Read the [release 38 | notes](https://github.com/rstudio/packrat/blob/master/NEWS.md) to learn what's 39 | new in Packrat. 40 | 41 | # Quick-start Guide 42 | 43 | Start by installing Packrat: 44 | 45 | install.packages("packrat") 46 | 47 | Then, start a new R session at the base directory of your project and type: 48 | 49 | packrat::init() 50 | 51 | This will install Packrat, set up a private library to be used for this 52 | project, and then place you in `packrat mode`. While in packrat mode, calls to 53 | functions like `install.packages` and `remove.packages` will modify the 54 | private project library, rather than the user library. 55 | 56 | When you want to manage the state of your private library, you can use the 57 | Packrat functions: 58 | 59 | - `packrat::snapshot()`: Save the current state of your library. 60 | - `packrat::restore()`: Restore the library state saved in the most recent 61 | snapshot. 62 | - `packrat::clean()`: Remove unused packages from your library. 63 | 64 | Share a Packrat project with `bundle` and `unbundle`: 65 | - `packrat::bundle()`: Bundle a packrat project, for easy sharing. 66 | - `packrat::unbundle()`: Unbundle a packrat project, generating a project 67 | directory with libraries restored from the most recent snapshot. 68 | 69 | Navigate projects and set/get options with: 70 | - `packrat::on()`, `packrat::off()`: Toggle packrat mode on and off, for 71 | navigating between projects within a single R session. 72 | - `packrat::get_opts`, `packrat::set_opts`: Get/set project-specific settings. 73 | 74 | Manage ad-hoc local repositories (note that these are a separate entity from 75 | CRAN-like repositories): 76 | - `packrat::set_opts(local.repos = ...)` can be used to specify *local 77 | repositories*; that is, directories containing (unzipped) package sources. 78 | - `packrat::install_local()` installs packages available in a local 79 | repository. 80 | 81 | For example, suppose I have the (unzipped) package sources for 82 | [`digest`](https://cran.r-project.org/package=digest) located 83 | within the folder`~/git/R/digest/`. To install this package, you can use: 84 | 85 | packrat::set_opts(local.repos = "~/git/R") 86 | packrat::install_local("digest") 87 | 88 | There are also utility functions for using and managing packages in the 89 | external / user library, and can be useful for leveraging packages in the user 90 | library that you might not want as project-specific dependencies, e.g. 91 | `devtools`, `knitr`, `roxygen2`: 92 | 93 | - `packrat::extlib()`: Load an external package. 94 | - `packrat::with_extlib()`: With an external package, evaluate an expression. 95 | The external package is loaded only for the duration of the evaluated 96 | expression, but note that there may be other side effects associated with 97 | the package's `.onLoad`, `.onAttach` and `.onUnload` calls that we may not 98 | be able to fully control. 99 | 100 | # Workflows 101 | 102 | Packrat supports a set of common analytic workflows: 103 | 104 | 1. `As-you-go`: use `packrat::init()` to initialize packrat with your project, 105 | and use it to manage your project library while you develop your analysis. 106 | As you install and remove packages, you can use `packrat::snapshot()` and 107 | `packrat::restore()` to maintain the R packages in your project. For 108 | collaboration, you can either use your favourite version control system, or 109 | use `packrat::bundle()` to generate a bundled version of your project that 110 | collaborators can use with `packrat::unbundle()`. 111 | 112 | 2. `When-you're-done`: take an existing or complete analysis (preferably 113 | collected within one directory), and call `packrat::init()` to immediately 114 | obtain R package sources for all packages used in your project, and snapshot 115 | that state so it can hence be preserved across time. 116 | 117 | # Setting up your own custom, CRAN-like repositories 118 | 119 | Please view the [set-up 120 | guide](https://rstudio.github.io/packrat/custom-repos.html) here for a simple 121 | walkthrough in how you might set up your own, local, custom CRAN repository. 122 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | ## Release Instructions 2 | 3 | > Try to use `usethis::use_release_issue()` rather than this checklist. 4 | 5 | Create an issue with the following content, replacing `${RELEASE_VERSION}` and 6 | `${NEXT_RELEASE_VERSION}` with the current and next release versions. 7 | 8 | ````markdown 9 | ```console 10 | RELEASE_VERSION=0.9.1 11 | NEXT_RELEASE_VERSION=0.9.2 12 | ```console 13 | 14 | ### Prepare for release 15 | 16 | - [ ] Switch to `main` and pull. 17 | 18 | ```bash 19 | git checkout main 20 | git pull 21 | ``` 22 | 23 | - [ ] Create and switch to a release branch (e.g. `release/${RELEASE_VERSION}`). 24 | 25 | ```bash 26 | git checkout -b "release/${RELEASE_VERSION}" 27 | ``` 28 | 29 | - [ ] Update version in `DESCRIPTION` file. 30 | 31 | - [ ] Update header and version in `NEWS.md`. confirm recent changes are 32 | included. ([style reference](https://style.tidyverse.org/news.html#news-release)) 33 | 34 | - [ ] Update auto-loaders (from R): 35 | 36 | ```r 37 | source("R/update.R"); updateInit(); 38 | ``` 39 | 40 | - [ ] Commit your changes! 41 | 42 | ```bash 43 | git commit -m "preparing for ${RELEASE_VERSION} release" NEWS.md DESCRIPTION inst 44 | ``` 45 | 46 | - [ ] Check current CRAN check results: 47 | 48 | 49 | - [ ] Check that all URLs are valid (from R): 50 | 51 | ```r 52 | install.packages("urlchecker") 53 | urlchecker::url_check() 54 | ``` 55 | 56 | - [ ] Generate a release `.tar.gz` by running the following command from the 57 | parent directory of your `packrat` repository: 58 | 59 | ```console 60 | R CMD build packrat 61 | ``` 62 | 63 | - [ ] Test the package (also from the parent directory): 64 | 65 | ```console 66 | R CMD check --as-cran "packrat_${RELEASE_VERSION}.tar.gz" 67 | ``` 68 | 69 | - [ ] Push the `release/${RELEASE_VERSION}` branch to GitHub, create a PR, and let CI run. 70 | 71 | - [ ] Fix any issues identified by the previous steps. Rinse and repeat. 72 | 73 | ### Submit to CRAN 74 | 75 | - [ ] Submit to CRAN. Cross fingers. https://cran.r-project.org/ 76 | 77 | - [ ] Check your email; confirm package submission. 78 | 79 | - [ ] Wait for CRAN approval. 80 | 81 | ### Approved by CRAN 82 | 83 | - [ ] Squash-and-merge the PR with the `release/${RELEASE_VERSION}` changes back to `main`. 84 | 85 | - [ ] Create a git tag for your new release and push that tag. 86 | 87 | ```console 88 | git fetch 89 | git tag -a -m "CRAN release: v${RELEASE_VERSION}" "v${RELEASE_VERSION}" COMMIT_HASH 90 | git push origin "v${RELEASE_VERSION}" 91 | ``` 92 | 93 | - [ ] Create a GitHub release from the tag and include its NEWS.md items as 94 | release notes. 95 | 96 | - [ ] Create a branch to bump the version for development (e.g. `development/${NEXT_RELEASE_VERSION}`). 97 | 98 | ```console 99 | git checkout main 100 | git pull 101 | git checkout -b "development/${NEXT_RELEASE_VERSION}" 102 | ``` 103 | 104 | - [ ] Update `NEWS.md` with an "unreleased" version header. 105 | 106 | `````markdown 107 | # Packrat ${NEXT_RELEASE_VERSION} (UNRELEASED) 108 | ````` 109 | 110 | - [ ] Run the following command to update `DESCRIPTION` and the auto-loaders: 111 | 112 | ```console 113 | R -f configure.R 114 | ``` 115 | 116 | - [ ] Commit your changes! 117 | 118 | ```bash 119 | git commit -m "preparing for ${NEXT_RELEASE_VERSION} development" NEWS.md DESCRIPTION inst 120 | ``` 121 | 122 | - [ ] Push the `development/${NEXT_RELEASE_VERSION}` branch to GitHub, create 123 | a PR, and let CI run. 124 | 125 | - [ ] Squash-and-merge the PR with the `development/${NEXT_RELEASE_VERSION}` 126 | changes back to `main`. 127 | ```` 128 | 129 | ### Prerequisites 130 | 131 | You need a functional LaTeX installation in order to run some of these checks. 132 | 133 | ```r 134 | install.packages("tinytex") 135 | tinytex:::install_prebuilt('TinyTeX') 136 | ``` 137 | 138 | This installs a more full TeX install than occurs than 139 | `tinytex::install_tinytex` does by default. 140 | () 141 | -------------------------------------------------------------------------------- /announce/packrat-0.2.0.md: -------------------------------------------------------------------------------- 1 | # Packrat 0.2.0 2 | 3 | We're excited to announce version 0.2.0 of packrat! We've introduced a number 4 | of exciting features in this release: 5 | 6 | - **`packrat_mode`** allows you to seamlessly step in and out of packrat mode, 7 | for when you would would like to manage or use external projects while 8 | working with a packrat project. In addition, once you have entered packrat 9 | mode, the project directory is remembered for all later calls to packrat 10 | functions, e.g. `snapshot`, `clean`, `restore`, and so on -- so calling these 11 | functions without arguments will use the project directory, even if you have 12 | navigated outside of the project or to a project sub-directory. 13 | 14 | - The packrat project files have been migrated into a single `packrat/` folder 15 | -- this keeps pollution in the base directory of your project down. The 16 | remappings are: 17 | - `packrat.sources` -> `packrat/src`, 18 | - `library` -> `packrat/lib`, 19 | - `packrat.lock` -> `packrat/packrat.lock`, and 20 | - the `.Renviron` has been removed. 21 | 22 | - **`bundle`** and **`unbundle`** allow you to zip up your project as a tarball 23 | for easy sharing, 24 | 25 | - **`with_extlib`** and **`extlib`** allow you to (temporarily) load and use 26 | packages within the user library; this can be useful if you want to leverage 27 | another package (for example, `devtools::install_github`) while avoiding 28 | dependencies on `devtools` itself, 29 | 30 | - Packrat can now handle source package tarballs, rather than just source 31 | package folders, 32 | 33 | - A number of bugs relating to `status()` output have been fixed and tweaked, 34 | to give better information to the user. 35 | 36 | - Projects in packrat mode will have automatic, asynchronous snapshots for safe 37 | actions: with automatic snapshots on, packrat will automatically upgrade 38 | packages that are out of date, or add packages that are new to the lock file 39 | (e.g. when seen by an `install.packages()` call). Downgrades, removals and 40 | 'crossgrades' will be ignored and will require you to take an appropriate 41 | action (guided by the information provided by `status()`). 42 | 43 | - Packrat will warn you if you have user libraries in the system library path. 44 | In addition, packrat supplies a script for OS X users, to assist in migrating 45 | user packages from the system library to a separate user library. (By 46 | default, R versions compiled for Mac OS X install all packages into the 47 | system library; for packrat to function correctly we require that user and 48 | system libraries be separate -- this script should help facilitate the 49 | process. If you have any problems with migration, please let us know!) 50 | 51 | We will also be working on integration with the RStudio IDE in the coming 52 | weeks: here, we can provide a user-friendly interface for many of the packrat 53 | actions, and also leverage many tools within the IDE for better and smarter 54 | automatic updating of your packrat projects. Stay tuned! 55 | 56 | If you'd like to migrate a 'packrat 0.1.0' project to the new format, please do 57 | the following: 58 | 59 | 1. Navigate to your packrat project directory, 60 | 2. Remove the project `.Rprofile` file, 61 | 3. Start an R session in this folder, 62 | 4. Run the following script: 63 | 64 | if (!require("devtools")) install.packages("devtools") 65 | devtools::install_github("rstudio/packrat") 66 | packrat::migrate() 67 | 68 | After this, you can restart your R session, and you should be good to go! 69 | 70 | Thanks, Kevin 71 | 72 | -------------------------------------------------------------------------------- /configure.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env Rscript 2 | 3 | library(utils) 4 | 5 | args <- commandArgs(TRUE) 6 | 7 | # Extract the Version field from the DESCRIPTION. 8 | DESCRIPTION <- readLines("DESCRIPTION") 9 | idx <- grep("^Version:", DESCRIPTION) 10 | field <- DESCRIPTION[[idx]] 11 | 12 | # Figure out what the minor-patch bumped version is. 13 | bumpedDescVersion <- if (!grepl("-", DESCRIPTION[[idx]])) { 14 | paste(field, "-1", sep = "") 15 | } else { 16 | minorVersion <- as.numeric(gsub(".*-", "", DESCRIPTION[[idx]])) 17 | minorVersion <- minorVersion + 1 18 | gsub("-.*", paste("-", minorVersion, sep = ""), DESCRIPTION[[idx]]) 19 | } 20 | 21 | # Set the version field (use command line args if appropriate) 22 | version <- if (length(args)) { 23 | paste("Version:", args[[1]]) 24 | } else { 25 | bumpedDescVersion 26 | } 27 | 28 | DESCRIPTION[[idx]] <- version 29 | cat(DESCRIPTION, file = "DESCRIPTION", sep = "\n") 30 | 31 | source("R/update.R") 32 | updateInit() 33 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | 3 | * correct package docs for roxygen2 change. 4 | * addresses minor issues seen by users. 5 | 6 | ## R CMD check results 7 | 8 | 0 errors ✔ | 0 warnings ✔ | 0 notes ✔ 9 | 10 | ## revdepcheck results 11 | 12 | We checked 5 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package. 13 | 14 | * We saw 0 new problems 15 | * We failed to check 0 packages 16 | 17 | -------------------------------------------------------------------------------- /inst/resources/init-rprofile.R: -------------------------------------------------------------------------------- 1 | #### -- Packrat Autoloader (version 0.9.1-1) -- #### 2 | source("packrat/init.R") 3 | #### -- End Packrat Autoloader -- #### 4 | -------------------------------------------------------------------------------- /inst/resources/mac_r_userlib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # R system library to user library migration script for Mac OS X 6 | # 7 | # Date: January 14, 2014 8 | # Author: Joe Cheng 9 | # 10 | # From https://cran.r-project.org/bin/macosx/RMacOSX-FAQ.html: 11 | # The official CRAN binaries come pre-packaged in such a way that 12 | # administrator have sufficient privileges to update R and install 13 | # packages system-wide. 14 | # 15 | # This means that any install.packages() call, or using Install Package 16 | # from RStudio, causes packages to be installed in the system library 17 | # (e.g. /Library/Frameworks/R.framework/Versions/3.0/Resources/library). 18 | # The system library contains base and recommended packages as well. 19 | # 20 | # We believe it's more hygienic to keep base/recommended packages 21 | # separate from user-installed packages, and this separation is 22 | # necessary for the Packrat[0] dependency management system to provide 23 | # isolation benefits. 24 | # 25 | # This script creates a personal library directory, and migrates any 26 | # non-base, non-recommended packages from the system library into 27 | # it. It then sets the permissions on the system library to only be 28 | # writable by root. This will ensure that future install.packages calls 29 | # will not add more packages to the system library. 30 | # 31 | # [0] https://rstudio.github.io/packrat/ 32 | 33 | 34 | # The system-wide library 35 | RLIBDIR=`R --vanilla -s -e "cat(tail(.libPaths(), 1))"` 36 | 37 | # The user library (which might not exist yet) 38 | RLIBSUSER=`R --vanilla -s -e "cat(path.expand(head(Sys.getenv('R_LIBS_USER'), 1)))"` 39 | 40 | # The list of non-base, non-recommended packages in the system-wide library 41 | PKGS=`R --vanilla -s -e "cat(with(as.data.frame(installed.packages(tail(.libPaths(), 1))), paste(Package[is.na(Priority)])))"` 42 | 43 | if [ "$RLIBDIR" == "" ]; then 44 | echo "ERROR: Couldn't detect system library directory, aborting" >&2 45 | exit 1 46 | fi 47 | 48 | if [ "$RLIBSUSER" == "" ]; then 49 | echo "ERROR: Couldn't detect R_LIBS_USER directory, aborting" >&2 50 | exit 1 51 | fi 52 | 53 | echo "Saving backup of $RLIBDIR to ./SystemLibBackup.tar.gz" 54 | if [ -f ./SystemLibBackup.tar.gz ]; then 55 | echo "SystemLibBackup.tar.gz exists. Press Enter to overwrite, or Ctrl-C to abort:" >&2 56 | read -s < /dev/tty 57 | echo "Backing up..." 58 | fi 59 | tar -czPf SystemLibBackup.tar.gz "$RLIBDIR" 60 | #tar -czf SystemLibBackup.tar.gz -C "$RLIBDIR" $(ls $RLIBDIR) 61 | echo "Backup successful." 62 | 63 | echo "Migrating user-installed packages to $RLIBSUSER" 64 | echo "Press Enter to continue, or Ctrl-C to abort" 65 | read -s < /dev/tty 66 | 67 | mkdir -p "$RLIBSUSER" 68 | 69 | for pkg in $PKGS; do 70 | echo "Moving $pkg" 71 | if [ -d "$RLIBSUSER/$pkg" ]; then 72 | echo "ERROR: The directory $RLIBSUSER/$pkg already exists, aborting" >&2 73 | echo "Please delete the package $pkg from either $RLIBDIR or $RLIBSUSER." 74 | exit 3 75 | fi 76 | # Do a copy to get default permissions 77 | cp -R "$RLIBDIR/$pkg" "$RLIBSUSER" 78 | sudo rm -rf "$RLIBDIR/$pkg" 79 | done 80 | 81 | echo 82 | echo "Making $RLIBDIR writable only by root (chmod 755)" 83 | sudo chmod -R 755 "$RLIBDIR" 84 | 85 | echo 86 | echo Success! 87 | -------------------------------------------------------------------------------- /inst/rstudio/rstudio-protocol: -------------------------------------------------------------------------------- 1 | Version: 1 2 | -------------------------------------------------------------------------------- /internal/digestPkg.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 | -------------------------------------------------------------------------------- /internal/digestPkg.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ## Testing a package using a source package tarball 4 | PACKAGE_NAME="digestPkg" 5 | cd ~/git 6 | R CMD INSTALL packrat 7 | rm -rf ${PACKAGE_NAME} 8 | mkdir ${PACKAGE_NAME} 9 | cd ${PACKAGE_NAME} 10 | touch foo.R bar.R baz.R 11 | echo "library(digest)" >> foo.R 12 | cp ~/git/packrat/internal/digestPkg.Rproj ~/git/${PACKAGE_NAME}/ 13 | R --vanilla -e "options(repos = c(CRAN = 'https://cran.rstudio.org')); library(packrat); dir.create('.git'); init(options = list(local.repos = '~/git'))" 14 | R 15 | -------------------------------------------------------------------------------- /internal/shinyPkg.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ## Testing a package using a source package tarball 4 | PACKAGE_NAME="shinyPkg" 5 | cd ~/git 6 | R CMD INSTALL packrat 7 | rm -rf ${PACKAGE_NAME} 8 | mkdir ${PACKAGE_NAME} 9 | cd ${PACKAGE_NAME} 10 | touch foo.R bar.R baz.R 11 | echo "library(shiny)" >> foo.R 12 | cp ~/git/packrat/internal/digestPkg.Rproj ~/git/${PACKAGE_NAME}/ 13 | R --vanilla -e "options(repos = c(CRAN = 'https://cran.rstudio.org')); library(packrat); dir.create('.git'); init(options = list(local.repos = '~/git'))" 14 | R 15 | -------------------------------------------------------------------------------- /internal/testPkg.sh: -------------------------------------------------------------------------------- 1 | ## Launch into a test package using packrat 2 | cd ~/git 3 | R CMD build packrat && R CMD INSTALL packrat_0.2.0.99.tar.gz 4 | rm -rf testPkg 5 | mkdir testPkg 6 | cd testPkg 7 | touch foo.R bar.R baz.R 8 | echo "library(digest)" >> foo.R 9 | cp ~/git/digest/DESCRIPTION ~/git/testPkg/DESCRIPTION 10 | R --vanilla -e "options(repos = c(CRAN = 'https://cran.rstudio.org')); library(packrat); dir.create('.git'); bootstrap(source='~/git/packrat')" 11 | R 12 | -------------------------------------------------------------------------------- /man/appDependencies.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dependencies.R 3 | \name{appDependencies} 4 | \alias{appDependencies} 5 | \title{Detect Application Dependencies} 6 | \usage{ 7 | appDependencies( 8 | project = NULL, 9 | available.packages = NULL, 10 | fields = opts$snapshot.fields(), 11 | implicit.packrat.dependency = TRUE 12 | ) 13 | } 14 | \arguments{ 15 | \item{project}{Directory containing application. Defaults to current working 16 | directory.} 17 | 18 | \item{implicit.packrat.dependency}{Include \code{packrat} as an implicit 19 | dependency of this project, if not otherwise discovered? This should be 20 | \code{FALSE} only if you can guarantee that \code{packrat} will be available 21 | via other means when attempting to load this project.} 22 | } 23 | \value{ 24 | Returns a list of the names of the packages on which R code in the 25 | application depends. 26 | } 27 | \description{ 28 | Recursively detect all package dependencies for an application. This function 29 | parses all \R files in the application directory to determine what packages 30 | the application depends directly. 31 | } 32 | \details{ 33 | Only direct dependencies are detected (i.e. no recursion is done to find the 34 | dependencies of the dependencies). 35 | 36 | Dependencies are determined by parsing application source code and 37 | looking for calls to \code{library}, \code{require}, \code{::}, and 38 | \code{:::}. 39 | } 40 | \examples{ 41 | 42 | \dontrun{ 43 | 44 | # dependencies for the app in the current working dir 45 | appDependencies() 46 | 47 | # dependencies for an app in another directory 48 | appDependencies("~/projects/shiny/app1") 49 | 50 | } 51 | } 52 | \keyword{internal} 53 | -------------------------------------------------------------------------------- /man/bundle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bundle.R 3 | \name{bundle} 4 | \alias{bundle} 5 | \title{Bundle a Packrat Project} 6 | \usage{ 7 | bundle( 8 | project = NULL, 9 | file = NULL, 10 | include.src = TRUE, 11 | include.lib = FALSE, 12 | include.bundles = TRUE, 13 | include.vcs.history = FALSE, 14 | overwrite = FALSE, 15 | omit.cran.src = FALSE, 16 | ... 17 | ) 18 | } 19 | \arguments{ 20 | \item{project}{The project directory. Defaults to the currently activate 21 | project. By default, the current project active under \code{packratMode} 22 | is checked.} 23 | 24 | \item{file}{The path to write the bundle. By default, we write 25 | the bundle to \code{packrat/bundles/-.tar.gz}, with 26 | \code{} as returned by \code{Sys.date()}.} 27 | 28 | \item{include.src}{Include the packrat sources?} 29 | 30 | \item{include.lib}{Include the packrat private library?} 31 | 32 | \item{include.bundles}{Include other packrat bundle tarballs 33 | (as in \code{packrat/bundles/})?} 34 | 35 | \item{include.vcs.history}{Include version control history (ie, \code{.git/} 36 | or \code{.svn/} folders)?} 37 | 38 | \item{overwrite}{Boolean; overwrite the file at \code{file} if it already exists?} 39 | 40 | \item{omit.cran.src}{Boolean; when \code{TRUE}, packages whose sources can 41 | be retrieved from CRAN are excluded from the bundle.} 42 | 43 | \item{...}{Optional arguments passed to \code{\link{tar}}.} 44 | } 45 | \value{ 46 | The path (invisibly) to the bundled project. 47 | } 48 | \description{ 49 | Bundle a packrat project, for easy sharing. 50 | } 51 | \details{ 52 | The project is bundled as a gzipped tarball (\code{.tar.gz}), which can 53 | be unbundled either with \code{packrat::\link{unbundle}} (which 54 | restores the project as well), \R's own \code{utils::\link{untar}}, or 55 | through most system \code{tar} implementations. 56 | 57 | The tar binary is selected using the same heuristic as \code{\link{restore}}. 58 | } 59 | -------------------------------------------------------------------------------- /man/clean.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/packrat.R 3 | \name{clean} 4 | \alias{clean} 5 | \title{Remove Packages from the Library} 6 | \usage{ 7 | clean( 8 | packages = NULL, 9 | project = NULL, 10 | lib.loc = libDir(project), 11 | dry.run = FALSE, 12 | force = FALSE 13 | ) 14 | } 15 | \arguments{ 16 | \item{packages}{A set of package names to remove from the project. When 17 | \code{NULL}, \code{\link{unused_packages}} is used to find packages 18 | unused in the project.} 19 | 20 | \item{project}{The project directory. Defaults to current working 21 | directory.} 22 | 23 | \item{lib.loc}{The library to clean. Defaults to the private package library 24 | associated with the project directory.} 25 | 26 | \item{dry.run}{Perform a dry run, returning records on which packages would 27 | have been moved by the current clean action.} 28 | 29 | \item{force}{Force package removal, even if they are still in use within the project?} 30 | } 31 | \description{ 32 | Remove packages from the given library. 33 | } 34 | \examples{ 35 | \dontrun{ 36 | 37 | # Get unused package records 38 | unused_packages() 39 | 40 | # Clean all unused packages 41 | clean() 42 | 43 | # Clean specific packages 44 | clean("foo") 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /man/disable.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/disable.R 3 | \name{disable} 4 | \alias{disable} 5 | \title{Disable the use of Packrat in a Project} 6 | \usage{ 7 | disable(project = NULL, restart = TRUE) 8 | } 9 | \arguments{ 10 | \item{project}{The directory in which packrat will be disabled (defaults to 11 | the current working directory)} 12 | 13 | \item{restart}{If \code{TRUE}, restart the R session after disabling packrat.} 14 | } 15 | \description{ 16 | Disable packrat within a project, reverting to the use of standard user 17 | package libraries. 18 | } 19 | \note{ 20 | Disabling packrat for a project removes the packrat initialization code 21 | from the .Rprofile file, resulting in the use of standard user package 22 | libraries. Note that the \code{packrat} directory is not deleted, but remains 23 | unused. 24 | 25 | To re-enable the use of packrat for a project you can call the 26 | \code{\link{init}} function. 27 | 28 | The \code{restart} parameter will only result in a restart of R when the R 29 | environment packrat is running within makes available a restart function via 30 | \code{getOption("restart")}. 31 | } 32 | -------------------------------------------------------------------------------- /man/init.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/packrat.R 3 | \name{init} 4 | \alias{init} 5 | \title{Initialize Packrat on a new or existing \R project} 6 | \usage{ 7 | init( 8 | project = ".", 9 | options = NULL, 10 | enter = TRUE, 11 | restart = enter, 12 | infer.dependencies = TRUE 13 | ) 14 | } 15 | \arguments{ 16 | \item{project}{The directory that contains the \R project.} 17 | 18 | \item{options}{An \R \code{list} of options, as specified in 19 | \code{\link{packrat-options}}.} 20 | 21 | \item{enter}{Boolean, enter packrat mode for this project after finishing a init?} 22 | 23 | \item{restart}{If \code{TRUE}, restart the R session after init.} 24 | 25 | \item{infer.dependencies}{If \code{TRUE}, infer package dependencies by 26 | examining the \R code.} 27 | } 28 | \description{ 29 | Given a project directory, makes a new packrat project in the directory. 30 | } 31 | \details{ 32 | \code{init} works as follows: 33 | 34 | \enumerate{ 35 | 36 | \item Application dependencies are computed by examining the \R code 37 | throughout the project for \code{library} and \code{require} calls. You can 38 | opt out of this behavior by setting \code{infer.dependencies} to 39 | \code{FALSE}. 40 | 41 | \item A snapshot is taken of the version of each package currently used by 42 | the project as described in \code{\link{snapshot}}, and each package's 43 | sources are downloaded. 44 | 45 | \item A private library is created in the directory. 46 | 47 | \item The snapshot is applied to the directory as described in 48 | \code{\link{restore}}. } When \code{init} is finished, all the packages 49 | on which the project depends are installed in a new, private library located 50 | inside the project directory. 51 | 52 | \strong{You must restart your \R session in the given project directory after 53 | running \code{init} in order for the changes to take effect!} 54 | 55 | When \R is started in the directory, it will use the new, private library. 56 | Calls to \code{\link{require}} and \code{\link{library}} will load packages 57 | from the private library (except for 'base' or 'recommended' \R packages, 58 | which are found in the system library), and functions such as \code{\link{install.packages}} 59 | will modify that private library. You can sync this private library with 60 | packrat using \code{\link{snapshot}} and \code{\link{restore}}. 61 | } 62 | \note{ 63 | The \code{restart} parameter will only result in a restart of R when the 64 | R environment packrat is running within makes available a restart function 65 | via \code{getOption("restart")}. 66 | } 67 | \examples{ 68 | \dontrun{ 69 | 70 | ## initialize a project using a local repository of packages 71 | packrat::init(options = list(local.repos = "~/projects/R")) 72 | 73 | } 74 | } 75 | \seealso{ 76 | \link{packrat} for a description of the files created by 77 | \code{init}. 78 | } 79 | -------------------------------------------------------------------------------- /man/install.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install.R 3 | \name{install} 4 | \alias{install} 5 | \title{Install a local development package.} 6 | \usage{ 7 | install( 8 | pkg = ".", 9 | reload = TRUE, 10 | quick = FALSE, 11 | local = TRUE, 12 | args = getOption("devtools.install.args"), 13 | quiet = FALSE, 14 | dependencies = NA, 15 | build_vignettes = !quick, 16 | keep_source = getOption("keep.source.pkgs") 17 | ) 18 | } 19 | \arguments{ 20 | \item{pkg}{package description, can be path or package name.} 21 | 22 | \item{reload}{if \code{TRUE} (the default), will automatically reload the 23 | package after installing.} 24 | 25 | \item{quick}{if \code{TRUE} skips docs, multiple-architectures, 26 | demos, and vignettes, to make installation as fast as possible.} 27 | 28 | \item{local}{if \code{FALSE} \code{\link{build}}s the package first: 29 | this ensures that the installation is completely clean, and prevents any 30 | binary artefacts (like \file{.o}, \code{.so}) from appearing in your local 31 | package directory, but is considerably slower, because every compile has 32 | to start from scratch.} 33 | 34 | \item{args}{An optional character vector of additional command line 35 | arguments to be passed to \code{R CMD install}. This defaults to the 36 | value of the option \code{"devtools.install.args"}.} 37 | 38 | \item{quiet}{if \code{TRUE} suppresses output from this function.} 39 | 40 | \item{dependencies}{\code{logical} indicating to also install uninstalled 41 | packages which this \code{pkg} depends on/links to/suggests. See 42 | argument \code{dependencies} of \code{\link{install.packages}}.} 43 | 44 | \item{build_vignettes}{if \code{TRUE}, will build vignettes. Normally it is 45 | \code{build} that's responsible for creating vignettes; this argument makes 46 | sure vignettes are built even if a build never happens (i.e. because 47 | \code{local = TRUE}.} 48 | 49 | \item{keep_source}{If \code{TRUE} will keep the srcrefs from an installed 50 | package. This is useful for debugging (especially inside of RStudio). 51 | It defaults to the option \code{"keep.source.pkgs"}.} 52 | } 53 | \description{ 54 | Uses \code{R CMD INSTALL} to install the package. Will also try to install 55 | dependencies of the package from CRAN, if they're not already installed. 56 | } 57 | \details{ 58 | By default, installation takes place using the current package directory. 59 | If you have compiled code, this means that artefacts of compilation will be 60 | created in the \code{src/} directory. If you want to avoid this, you can 61 | use \code{local = FALSE} to first build a package bundle and then install 62 | it from a temporary directory. This is slower, but keeps the source 63 | directory pristine. 64 | 65 | If the package is loaded, it will be reloaded after installation. 66 | } 67 | -------------------------------------------------------------------------------- /man/install_local.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/install-local.R 3 | \name{install_local} 4 | \alias{install_local} 5 | \title{Install a Package from a Local Repository} 6 | \usage{ 7 | install_local(pkgs, ..., lib = .libPaths()[1], repos = get_opts("local.repos")) 8 | } 9 | \arguments{ 10 | \item{pkgs}{A character vector of package names.} 11 | 12 | \item{...}{Optional arguments passed to \code{\link[packrat]{install}}.} 13 | 14 | \item{lib}{The library in which the package should be installed.} 15 | 16 | \item{repos}{The local repositories to search for the package names specified.} 17 | } 18 | \description{ 19 | This function can be used to install a package from a local 'repository'; i.e., 20 | a directory containing package tarballs and sources. 21 | } 22 | -------------------------------------------------------------------------------- /man/lockfile-metadata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lockfile-metadata.R 3 | \name{lockfile-metadata} 4 | \alias{lockfile-metadata} 5 | \alias{set_lockfile_metadata} 6 | \alias{get_lockfile_metadata} 7 | \title{Get / Set packrat lockfile metadata} 8 | \usage{ 9 | set_lockfile_metadata(repos = NULL, r_version = NULL, project = NULL) 10 | 11 | get_lockfile_metadata(metadata = NULL, simplify = TRUE, project = NULL) 12 | } 13 | \arguments{ 14 | \item{repos}{A named character vector of the form \code{c( = "")}.} 15 | 16 | \item{r_version}{A length-one character vector with suitable numeric version 17 | string. See \code{\link[base]{package_version}}.} 18 | 19 | \item{project}{The project directory. When in packrat mode, defaults to the current project; 20 | otherwise, defaults to the current working directory.} 21 | 22 | \item{metadata}{The lockfile field name(s) to draw from.} 23 | 24 | \item{simplify}{Boolean; if \code{TRUE} the returned metadata will be un-listed.} 25 | } 26 | \description{ 27 | Get and set metadata in the current packrat-managed project lockfile \code{packrat.lock} 28 | } 29 | \details{ 30 | Project's \code{packrat.lock} contains some metadata before packages 31 | dependencies informations. The project's lockfile is created and updated 32 | programmatically by \code{\link{snapshot}}. However it could be necessary sometimes to 33 | modify manually some of those values. For example, it could be useful to set another repository 34 | CRAN url when deploying to a offline environnement. 35 | } 36 | \section{available metadata }{ 37 | 38 | 39 | \itemize{ 40 | \item \code{r_version}: R version the project depends on 41 | \item \code{repos}: Name of repos and their url recorded packages can be 42 | retrieve from. Only url is recommended to change if need. Name of repos is 43 | used in package records and must be identical 44 | } 45 | } 46 | 47 | \examples{ 48 | \dontrun{ 49 | # changes repos url 50 | repos <- old_repos <- get_lockfile_metadata("repos") 51 | repos 52 | repos["CRAN"] <- "https://cran.r-project.org/" 53 | set_lockfile_metadata(repos = repos) 54 | get_lockfile_metadata("repos") 55 | # setting back old state 56 | # set_lockfile_metadata(repos = old_repos) 57 | 58 | # changes R version 59 | rver <- old_rver <- get_lockfile_metadata("r_version") 60 | rver 61 | rver <- "3.4.1" 62 | set_lockfile_metadata(r_version = rver) 63 | get_lockfile_metadata("r_version") 64 | # Setting back old state 65 | # set_lockfile_metadata(r_version = old_rver) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /man/packify.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/packrat.R 3 | \name{packify} 4 | \alias{packify} 5 | \title{Automatically Enter Packrat Mode on Startup} 6 | \usage{ 7 | packify(project = NULL, quiet = FALSE) 8 | } 9 | \arguments{ 10 | \item{project}{The directory in which to install the \code{.Rprofile} file.} 11 | 12 | \item{quiet}{Be chatty?} 13 | } 14 | \description{ 15 | Install/augment the \code{.Rprofile} in a project, so that all \R sessions 16 | started in this directory enter \code{packrat mode}, and use the local 17 | project library. 18 | } 19 | \details{ 20 | It is not normally necessary to call \code{packify} directly; these files are 21 | normally installed by \code{\link{init}}. \code{packify} can be used to 22 | restore the files if they are missing (for instance, if they were not added to 23 | source control, or were accidentally removed). 24 | 25 | You'll need to restart \R in the specified directory after running 26 | \code{packify} in order to start using the private package library. 27 | } 28 | -------------------------------------------------------------------------------- /man/packrat-external.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/external.R, R/paths.R 3 | \name{packrat-external} 4 | \alias{packrat-external} 5 | \alias{with_extlib} 6 | \alias{extlib} 7 | \alias{user_lib} 8 | \alias{packrat_lib} 9 | \title{Managing External Libraries} 10 | \usage{ 11 | with_extlib(packages = NULL, expr, envir = parent.frame()) 12 | 13 | extlib(packages) 14 | 15 | user_lib() 16 | 17 | packrat_lib() 18 | } 19 | \arguments{ 20 | \item{packages}{An optional set of package names (as a character 21 | vector) to load for the duration of evaluation of \code{expr}. 22 | Whether \code{packages} is provided or \code{NULL} (the 23 | default), \code{expr} is evaluated in an environment where the 24 | external library path is in place, not the local (packrat) 25 | library path.} 26 | 27 | \item{expr}{An \R expression.} 28 | 29 | \item{envir}{An environment in which the expression is evaluated.} 30 | } 31 | \description{ 32 | These functions provide a mechanism for (temporarily) using packages outside 33 | of the packrat private library. The packages are searched within the 'default' 34 | libraries; that is, the libraries that would be available upon launching a new 35 | \R session. 36 | } 37 | \examples{ 38 | \dontrun{ 39 | with_extlib("lattice", xyplot(1 ~ 1)) 40 | with_extlib(expr = packageVersion("lattice")) 41 | # since devtools requires roxygen2 >= 5.0.0 for this step, this 42 | # should fail unless roxygen2 is available in the packrat lib.loc 43 | with_extlib("devtools", load_all("path/to/project")) 44 | # this method will work given roxygen2 is installed in the 45 | # non-packrat lib.loc with devtools 46 | with_extlib(expr = devtools::load_all("path/to/project")) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /man/packrat-mode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/packrat-mode.R 3 | \name{packrat-mode} 4 | \alias{packrat-mode} 5 | \alias{packrat_mode} 6 | \alias{on} 7 | \alias{off} 8 | \title{Packrat Mode} 9 | \usage{ 10 | packrat_mode( 11 | on = NULL, 12 | project = NULL, 13 | auto.snapshot = get_opts("auto.snapshot"), 14 | clean.search.path = FALSE 15 | ) 16 | 17 | on( 18 | project = NULL, 19 | auto.snapshot = get_opts("auto.snapshot"), 20 | clean.search.path = TRUE, 21 | print.banner = TRUE 22 | ) 23 | 24 | off(project = NULL, print.banner = TRUE) 25 | } 26 | \arguments{ 27 | \item{on}{Turn packrat mode on (\code{TRUE}) or off (\code{FALSE}). If omitted, packrat mode 28 | will be toggled.} 29 | 30 | \item{project}{The directory in which packrat mode is launched -- this is 31 | where local libraries will be used and updated.} 32 | 33 | \item{auto.snapshot}{Perform automatic, asynchronous snapshots?} 34 | 35 | \item{clean.search.path}{Detach and unload any packages loaded from non-system 36 | libraries before entering packrat mode?} 37 | 38 | \item{print.banner}{Print the packrat banner when entering / exiting packrat mode? 39 | The packrat banner informs you of the new packrat mode state, as well as the library 40 | path in use.} 41 | } 42 | \description{ 43 | Use these functions to switch \code{packrat} mode on and off. When within 44 | \code{packrat} mode, the \R session will use the private library generated 45 | for the current project. 46 | } 47 | -------------------------------------------------------------------------------- /man/packrat-options.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/options.R 3 | \docType{data} 4 | \name{packrat-options} 5 | \alias{packrat-options} 6 | \alias{get_opts} 7 | \alias{set_opts} 8 | \alias{opts} 9 | \title{Get/set packrat project options} 10 | \usage{ 11 | get_opts(options = NULL, simplify = TRUE, project = NULL) 12 | 13 | set_opts(..., project = NULL, persist = TRUE) 14 | 15 | opts 16 | } 17 | \arguments{ 18 | \item{options}{A character vector of valid option names.} 19 | 20 | \item{simplify}{Boolean; \code{unlist} the returned options? Useful for when retrieving 21 | a single option.} 22 | 23 | \item{project}{The project directory. When in packrat mode, defaults to the current project; 24 | otherwise, defaults to the current working directory.} 25 | 26 | \item{...}{Entries of the form \code{key = value}, used for setting packrat project options.} 27 | 28 | \item{persist}{Boolean; persist these options for future sessions?} 29 | } 30 | \description{ 31 | Get and set options for the current packrat-managed project. 32 | } 33 | \section{Valid Options}{ 34 | 35 | 36 | \itemize{ 37 | \item \code{auto.snapshot}: Perform automatic, asynchronous snapshots when running interactively? 38 | (logical; defaults to \code{FALSE}) 39 | \item \code{use.cache}: 40 | Install packages into a global cache, which is then shared across projects? The 41 | directory to use is read through \code{Sys.getenv("R_PACKRAT_CACHE_DIR")}. 42 | Windows support is currently experimental. 43 | (logical; defaults to \code{FALSE}) 44 | \item \code{print.banner.on.startup}: 45 | Print the banner on startup? Can be one of \code{TRUE} (always print), 46 | \code{FALSE} (never print), and \code{'auto'} (do the right thing) 47 | (defaults to \code{"auto"}) 48 | \item \code{vcs.ignore.lib}: 49 | If TRUE, version control configuration is modified to ignore packrat private libraries. 50 | (logical; defaults to \code{TRUE}) 51 | \item \code{vcs.ignore.src}: 52 | If TRUE, version control configuration is modified to ignore packrat private sources. 53 | (logical; defaults to \code{FALSE}) 54 | \item \code{external.packages}: 55 | Packages which should be loaded from the user library. This can be useful for 56 | very large packages which you don't want duplicated across multiple projects, 57 | e.g. BioConductor annotation packages, or for package development scenarios 58 | wherein you want to use e.g. \code{devtools} and \code{roxygen2} for package 59 | development, but do not want your package to depend on these packages. 60 | (character; defaults to \code{Sys.getenv("R_PACKRAT_EXTERNAL_PACKAGES")}) 61 | \item \code{local.repos}: 62 | Ad-hoc local 'repositories'; i.e., directories containing package sources within 63 | sub-directories. 64 | (character; empty by default) 65 | \item \code{load.external.packages.on.startup}: 66 | Load any packages specified within \code{external.packages} on startup? 67 | (logical; defaults to \code{TRUE}) 68 | \item \code{ignored.packages}: 69 | Prevent packrat from tracking certain packages. Dependencies of these packages 70 | will also not be tracked (unless these packages are encountered as dependencies 71 | in a separate context from the ignored package). 72 | (character; empty by default) 73 | \item \code{ignored.directories}: 74 | Prevent packrat from looking for dependencies inside certain directories of your 75 | workspace. For example, if you have set your "local.repos" to be inside your local 76 | workspace so that you can track custom packages as git submodules. 77 | Each item should be the relative path to a directory in the workspace, e.g. "data", 78 | "lib/gitsubmodule". Note that packrat already ignores any "invisible" files and 79 | directories, such as those whose names start with a "." character. 80 | (character; empty by default) 81 | \item \code{quiet.package.installation}: 82 | Emit output during package installation? 83 | (logical; defaults to \code{TRUE}) 84 | \item \code{snapshot.recommended.packages}: 85 | Should 'recommended' packages discovered in the system library be 86 | snapshotted? See the \code{Priority} field of \code{available.packages()} 87 | for more information -- 'recommended' packages are those normally bundled 88 | with CRAN releases of R on OS X and Windows, but new releases are also 89 | available on the CRAN server. 90 | (logical; defaults to \code{FALSE}) 91 | \item \code{snapshot.fields}: 92 | What fields of a package's DESCRIPTION file should be used when discovering 93 | dependencies? 94 | (character, defaults to \code{c("Imports", "Depends", "LinkingTo")}) 95 | \item \code{symlink.system.packages}: 96 | Symlink base \R packages into a private \code{packrat/lib-R} directory? 97 | This is done to further encapsulate the project from user packages that 98 | have been installed into the \R system library. 99 | (boolean, defaults to \code{TRUE}) 100 | } 101 | } 102 | 103 | \examples{ 104 | \dontrun{ 105 | ## use 'devtools' and 'knitr' from the user library 106 | packrat::set_opts(external.packages = c("devtools", "knitr")) 107 | 108 | ## set local repository 109 | packrat::set_opts(local.repos = c("~/projects/R")) 110 | 111 | ## get the set of 'external packages' 112 | packrat::opts$external.packages() 113 | 114 | ## set the external packages 115 | packrat::opts$external.packages(c("devtools", "knitr")) 116 | } 117 | } 118 | \keyword{datasets} 119 | -------------------------------------------------------------------------------- /man/packrat-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/packrat.R 3 | \docType{package} 4 | \name{packrat-package} 5 | \alias{packrat} 6 | \alias{packrat-package} 7 | \title{Packrat: Reproducible dependency management} 8 | \description{ 9 | Packrat is a tool for managing the \R packages your project depends on in 10 | an isolated, portable, and reproducible way. 11 | } 12 | \details{ 13 | Use packrat to make your \R projects more: 14 | 15 | \itemize{ 16 | \item \strong{Isolated}: Installing a new or updated package for one project 17 | won't break your other projects, and vice versa. That's because packrat gives 18 | each project its own private package library. 19 | \item \strong{Portable}: Easily transport your projects from one computer to 20 | another, even across different platforms. Packrat makes it easy to install the 21 | packages your project depends on. 22 | \item \strong{Reproducible}: Packrat records the exact package versions you 23 | depend on, and ensures those exact versions are the ones that get installed 24 | wherever you go. 25 | } 26 | 27 | Use \code{\link{init}} to create a new packrat project, 28 | \code{\link{snapshot}} to record changes to your project's library, and 29 | \code{\link{restore}} to recreate your library the way it was the last time you 30 | (or anyone!) took a snapshot. 31 | 32 | Using these simple functions and sharing packrat's files lets you collaborate 33 | in a shared, consistent environment with others as your project grows and 34 | changes, and provides an easy way to share your results when you're done. 35 | } 36 | \section{Anatomy of a packrat project}{ 37 | 38 | 39 | A packrat project contains a few extra files and directories. The 40 | \code{\link{init}} function creates these files for you, if they don't 41 | already exist. 42 | 43 | \describe{ 44 | \item{\code{packrat/lib/}}{Private package library for this project.} 45 | \item{\code{packrat/src/}}{Source packages of all the dependencies that 46 | packrat has been made aware of.} 47 | 48 | \item{\code{packrat/packrat.lock}}{Lists the precise package versions that were used 49 | to satisfy dependencies, including dependencies of dependencies. (This file 50 | should never be edited by hand!)} 51 | 52 | \item{\code{.Rprofile}}{Directs \R to use the private package 53 | library (when it is started from the project directory).} 54 | } 55 | } 56 | 57 | \section{Using packrat with version control}{ 58 | 59 | 60 | Packrat is designed to work hand in hand with Git, Subversion, or any other 61 | version control system. Be sure to check in the \code{.Rprofile}, 62 | \code{packrat.lock} files, and everything under 63 | \code{packrat/src/}. You can tell your VCS to ignore \code{packrat/lib/} (or 64 | feel free to check it in if you don't mind taking up some extra space in your 65 | repository). 66 | } 67 | 68 | \examples{ 69 | \dontrun{ 70 | # Create a new packrat project from an existing directory of \R code 71 | init() 72 | 73 | # Install a package and take a snapshot of the new state of the library 74 | install.packages("TTR") 75 | snapshot() 76 | 77 | # Accidentally remove a package and restore to add it back 78 | remove.packages("TTR") 79 | restore() 80 | } 81 | 82 | } 83 | \seealso{ 84 | Useful links: 85 | \itemize{ 86 | \item \url{https://github.com/rstudio/packrat} 87 | \item Report bugs at \url{https://github.com/rstudio/packrat/issues} 88 | } 89 | 90 | } 91 | \author{ 92 | Posit Software, PBC 93 | } 94 | -------------------------------------------------------------------------------- /man/packrat-resources.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/paths.R 3 | \name{packrat-resources} 4 | \alias{packrat-resources} 5 | \alias{project_dir} 6 | \alias{src_dir} 7 | \alias{lib_dir} 8 | \alias{bundles_dir} 9 | \title{Paths to Packrat Resources} 10 | \usage{ 11 | project_dir(project = NULL) 12 | 13 | src_dir(project = NULL) 14 | 15 | lib_dir(project = NULL) 16 | 17 | bundles_dir(project = NULL) 18 | } 19 | \arguments{ 20 | \item{project}{The project directory.} 21 | } 22 | \description{ 23 | These functions provide a mechanism for retrieving the paths to 24 | Packrat resource directories. Each of these directories can be 25 | overridden by setting either an environment variable, or an \R 26 | option. 27 | } 28 | \section{Project Directory}{ 29 | 30 | 31 | \code{project_dir()} is special -- the \code{R_PACKRAT_PROJECT_DIR} 32 | environment variable is set and unset by \code{\link{on}} and 33 | \code{\link{off}}, respectively, and generally should not be 34 | overridden by the user. 35 | } 36 | 37 | \section{Directory Resolution}{ 38 | 39 | 40 | The following table shows the order in which resource directories 41 | are discovered (from left to right). The first non-empty result is 42 | used. 43 | 44 | \tabular{llll}{ 45 | \strong{API} \tab \strong{Environment Variable} \tab \strong{R Option} \tab \strong{Default Value} \cr 46 | \code{project_dir()} \tab \code{R_PACKRAT_PROJECT_DIR} \tab \code{packrat.project.dir} \tab \code{getwd()} \cr 47 | \code{src_dir()} \tab \code{R_PACKRAT_SRC_DIR} \tab \code{packrat.src.dir} \tab \code{"packrat/src"} \cr 48 | \code{lib_dir()} \tab \code{R_PACKRAT_LIB_DIR} \tab \code{packrat.lib.dir} \tab \code{"packrat/lib"} \cr 49 | \code{bundles_dir()} \tab \code{R_PACKRAT_BUNDLES_DIR} \tab \code{packrat.bundles.dir} \tab \code{"packrat/bundles"} \cr 50 | \emph{(none)} \tab \code{R_PACKRAT_LIB_R_DIR} \tab \code{packrat.lib-r.dir} \tab \code{"packrat/lib-R"} \cr 51 | \emph{(none)} \tab \code{R_PACKRAT_LIB_EXT_DIR} \tab \code{packrat.lib-ext.dir} \tab \code{"packrat/lib-ext"} \cr 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /man/repos_create.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cranlike-repositories.R 3 | \name{repos_create} 4 | \alias{repos_create} 5 | \title{Create a Local, CRAN-like Repository} 6 | \usage{ 7 | repos_create(path, name = basename(path), add = TRUE) 8 | } 9 | \arguments{ 10 | \item{path}{Path to a local CRAN-like repository.} 11 | 12 | \item{name}{The name to assign to the repository. Defaults to the 13 | directory name in which the reopsitory is created.} 14 | 15 | \item{add}{Add this new repository to the current set of repositories?} 16 | } 17 | \description{ 18 | Generate a local CRAN-like repository which can be 19 | used to store and distribute \R packages. 20 | } 21 | -------------------------------------------------------------------------------- /man/repos_upload.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cranlike-repositories.R 3 | \name{repos_upload} 4 | \alias{repos_upload} 5 | \title{Upload a Package to a Local CRAN-like Repository} 6 | \usage{ 7 | repos_upload(package, to, ...) 8 | } 9 | \arguments{ 10 | \item{package}{Path to a package tarball. The tarball should be 11 | created by \code{R CMD build}; alternatively, it can be the path 12 | to a folder containing the source code for a package (which 13 | will then be built with \code{R CMD build}) and then uploaded 14 | to the local repository.} 15 | 16 | \item{to}{The name of the CRAN-like repository. It (currently) must 17 | be a local (on-disk) CRAN repository.} 18 | 19 | \item{...}{Optional arguments passed to \code{R CMD build}.} 20 | } 21 | \description{ 22 | Upload a Package to a Local CRAN-like Repository 23 | } 24 | -------------------------------------------------------------------------------- /man/repository-management.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cranlike-repositories.R 3 | \name{repository-management} 4 | \alias{repository-management} 5 | \alias{repos_add} 6 | \alias{repos_add_local} 7 | \alias{repos_set} 8 | \alias{repos_set_local} 9 | \alias{repos_remove} 10 | \alias{repos_list} 11 | \title{Add a Repository} 12 | \usage{ 13 | repos_add(..., overwrite = FALSE) 14 | 15 | repos_add_local(..., overwrite = FALSE) 16 | 17 | repos_set(...) 18 | 19 | repos_set_local(...) 20 | 21 | repos_remove(names) 22 | 23 | repos_list() 24 | } 25 | \arguments{ 26 | \item{...}{Named arguments of the form \code{ = }.} 27 | 28 | \item{overwrite}{Boolean; overwrite if a repository with the given name 29 | already exists?} 30 | 31 | \item{names}{The names of repositories (as exist in e.g. 32 | \code{names(getOption("repos"))}).} 33 | } 34 | \description{ 35 | Add a repository to the set of currently available repositories. This is 36 | effectively an easier-to-use wrapper over interacting with the 37 | \code{"repos"} option, which is otherwise set with \code{options(repos = ...)}. 38 | } 39 | \details{ 40 | \code{repos_add_local} is used for adding file-based repositories; that is, 41 | CRAN repositories that live locally on disk and not on the internet / local network. 42 | } 43 | -------------------------------------------------------------------------------- /man/restore.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/packrat.R 3 | \name{restore} 4 | \alias{restore} 5 | \title{Apply the most recent snapshot to the library} 6 | \usage{ 7 | restore( 8 | project = NULL, 9 | overwrite.dirty = FALSE, 10 | prompt = interactive(), 11 | dry.run = FALSE, 12 | restart = !dry.run 13 | ) 14 | } 15 | \arguments{ 16 | \item{project}{The project directory. When in packrat mode, if this is 17 | \code{NULL}, then the directory associated with the current packrat project 18 | is used. Otherwise, the project directory specified is used.} 19 | 20 | \item{overwrite.dirty}{A dirty package is one that has been changed since the 21 | last snapshot or restore. Packrat will leave these alone by default. If you 22 | want to guarantee that \code{restore} will put you in the exact state 23 | represented by the snapshot being applied, use \code{overwrite.dirty = 24 | TRUE}.} 25 | 26 | \item{prompt}{\code{TRUE} to prompt before performing potentially destructive 27 | changes (package removals or downgrades); \code{FALSE} to perform these 28 | operations without confirmation.} 29 | 30 | \item{dry.run}{If \code{TRUE}, compute the changes to your packrat state that 31 | would be made if a restore was performed, without actually executing them.} 32 | 33 | \item{restart}{If \code{TRUE}, restart the R session after restoring.} 34 | } 35 | \description{ 36 | Applies the most recent snapshot to the project's private library. 37 | } 38 | \details{ 39 | \code{restore} works by adding, removing, and changing packages so that the 40 | set of installed packages and their versions matches the snapshot exactly. 41 | 42 | There are three common use cases for \code{restore}: 43 | \itemize{ 44 | \item \strong{Hydrate}: Use \code{restore} after copying a project to a new machine 45 | to populate the library on that machine. 46 | \item \strong{Sync}: Use \code{restore} to apply library changes made by a 47 | collaborator to your own library. (In general, you want to run \code{restore} 48 | whenever you pick up a change to \code{packrat.lock}) 49 | \item \strong{Rollback}: Use \code{restore} to undo accidental changes made 50 | to the library since the last snapshot. 51 | } 52 | 53 | \code{restore} cannot make changes to packages that are currently loaded. If 54 | changes are necessary to currently loaded packages, you will need to restart 55 | \R to apply the changes (\code{restore} will let you know when this is 56 | necessary). It is recommended that you do this as soon as possible, because 57 | any library changes made between running \code{restore} and restarting \R 58 | will be lost. 59 | } 60 | \note{ 61 | \code{restore} can be destructive; it will remove packages that were 62 | not in the snapshot, and it will replace newer packages with older versions 63 | if that's what the snapshot indicates. \code{restore} will warn you before 64 | attempting to remove or downgrade a package (if \code{prompt} is 65 | \code{TRUE}), but will always perform upgrades and new installations 66 | without prompting. 67 | 68 | \code{restore} works only on the private package library created by 69 | packrat; if you have other libraries on your path, they will be unaffected. 70 | 71 | The \code{restart} parameter will only result in a restart of R when the R 72 | environment packrat is running within makes available a restart function 73 | via \code{getOption("restart")}. 74 | 75 | To install packages hosted in private repositories on GitHub, GitLab, and 76 | Bitbucket, you must either set the option 77 | \code{packrat.authenticated.downloads.use.renv} to \code{TRUE} and ensure 78 | that \code{curl} is available on your system, or ensure that the 79 | \code{httr} package is available in your R library. 80 | 81 | In addition, you must make credentials for your provider available in the 82 | appropriate environment variable(s): \code{GITHUB_PAT}, \code{GITLAB_PAT}, 83 | and/or \code{BITBUCKET_USERNAME} and \code{BITBUCKET_PASSWORD}. These 84 | environment variables are hidden from package installation subprocesses. 85 | 86 | Packrat does not support installation from enterprise instances of GitHub, 87 | GitLab, or Bitbucket. 88 | 89 | Packrat selects a \code{tar} binary with the following heuristic: If a 90 | \code{TAR} environment variable exists, Packrat will use that. Otherwise, 91 | it will either look for a \code{tar} binary on the \code{PATH} on Unix, or 92 | look for the system \code{tar} on Windows. If no binary is found in those 93 | locations, it will use R's internal \code{tar} implementation, which may 94 | cause errors with long filenames. 95 | } 96 | \seealso{ 97 | \code{\link{snapshot}}, the command that creates the snapshots 98 | applied with \code{restore}. 99 | 100 | \code{\link{status}} to view the differences between the most recent 101 | snapshot and the library. 102 | } 103 | -------------------------------------------------------------------------------- /man/search_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/search-path.R 3 | \name{search_path} 4 | \alias{search_path} 5 | \title{Get Packages on the Search Path} 6 | \usage{ 7 | search_path() 8 | } 9 | \description{ 10 | Retrieve the packages on the search path, as well as the 11 | associated library location. 12 | } 13 | -------------------------------------------------------------------------------- /man/snapshot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/snapshot.R 3 | \name{snapshot} 4 | \alias{snapshot} 5 | \title{Capture and store the packages and versions in use} 6 | \usage{ 7 | snapshot( 8 | project = NULL, 9 | available = NULL, 10 | lib.loc = libDir(project), 11 | ignore.stale = FALSE, 12 | dry.run = FALSE, 13 | prompt = interactive(), 14 | snapshot.sources = TRUE, 15 | infer.dependencies = TRUE 16 | ) 17 | } 18 | \arguments{ 19 | \item{project}{The project directory. Defaults to current working 20 | directory.} 21 | 22 | \item{available}{A database of available packages.} 23 | 24 | \item{lib.loc}{The library to snapshot. Defaults to the private library 25 | associated with the given directory.} 26 | 27 | \item{ignore.stale}{Stale packages are packages that are different from the 28 | last snapshot, but were installed by packrat. Typically, packages become 29 | stale when a new snapshot is available, but you haven't applied it yet with 30 | \code{\link{restore}}. By default, packrat will prevent you from taking a 31 | snapshot when you have stale packages to prevent you from losing changes 32 | from the unapplied snapshot. If your intent is to overwrite the last 33 | snapshot without applying it, use \code{ignore.stale = TRUE} to skip this 34 | check.} 35 | 36 | \item{dry.run}{Computes the changes to your packrat state that would be made 37 | if a snapshot were performed, and prints them to the console.} 38 | 39 | \item{prompt}{\code{TRUE} to prompt before performing snapshotting package 40 | changes that might be unintended; \code{FALSE} to perform these operations 41 | without confirmation. Potentially unintended changes include snapshotting 42 | packages at an older version than the last snapshot, or missing despite 43 | being present in the last snapshot.} 44 | 45 | \item{snapshot.sources}{Boolean; should package sources be downloaded during 46 | snapshot?} 47 | 48 | \item{infer.dependencies}{If \code{TRUE}, infer package dependencies by 49 | examining \R code used within the project. This included the \R code 50 | contained within \code{.R} files, as well as other multi-mode documents 51 | (e.g. \code{.Rmd}).} 52 | } 53 | \description{ 54 | Finds the packages in use in the project, and stores a list 55 | of those packages, their sources, and their current versions in packrat. 56 | } 57 | \note{ 58 | \code{snapshot} modifies the project's \code{packrat.lock} file, and 59 | the sources stored in the project's \code{packrat/src} directory. If you 60 | are working with a version control system, your collaborators can sync the 61 | changes to these files and then use \code{\link{restore}} to apply your 62 | snapshot. 63 | } 64 | \examples{ 65 | \dontrun{ 66 | # Take a snapshot of the current project 67 | snapshot() 68 | 69 | # See what changes would be included in a snapshot 70 | snapshot(dry.run = TRUE) 71 | 72 | } 73 | } 74 | \seealso{ 75 | \code{\link{restore}} to apply a snapshot. 76 | \code{\link{status}} to view the differences between the most recent snapshot 77 | and the library. 78 | } 79 | -------------------------------------------------------------------------------- /man/snapshotImpl.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/snapshot.R 3 | \name{.snapshotImpl} 4 | \alias{.snapshotImpl} 5 | \title{Internal Snapshot Implementation} 6 | \usage{ 7 | .snapshotImpl( 8 | project, 9 | available = NULL, 10 | lib.loc = libDir(project), 11 | dry.run = FALSE, 12 | ignore.stale = FALSE, 13 | prompt = interactive(), 14 | auto.snapshot = FALSE, 15 | verbose = TRUE, 16 | fallback.ok = FALSE, 17 | snapshot.sources = TRUE, 18 | implicit.packrat.dependency = TRUE, 19 | infer.dependencies = TRUE 20 | ) 21 | } 22 | \arguments{ 23 | \item{project}{The project directory. Defaults to current working 24 | directory.} 25 | 26 | \item{available}{A database of available packages.} 27 | 28 | \item{lib.loc}{The library to snapshot. Defaults to the private library 29 | associated with the given directory.} 30 | 31 | \item{dry.run}{Computes the changes to your packrat state that would be made 32 | if a snapshot were performed, and prints them to the console.} 33 | 34 | \item{ignore.stale}{Stale packages are packages that are different from the 35 | last snapshot, but were installed by packrat. Typically, packages become 36 | stale when a new snapshot is available, but you haven't applied it yet with 37 | \code{\link{restore}}. By default, packrat will prevent you from taking a 38 | snapshot when you have stale packages to prevent you from losing changes 39 | from the unapplied snapshot. If your intent is to overwrite the last 40 | snapshot without applying it, use \code{ignore.stale = TRUE} to skip this 41 | check.} 42 | 43 | \item{prompt}{\code{TRUE} to prompt before performing snapshotting package 44 | changes that might be unintended; \code{FALSE} to perform these operations 45 | without confirmation. Potentially unintended changes include snapshotting 46 | packages at an older version than the last snapshot, or missing despite 47 | being present in the last snapshot.} 48 | 49 | \item{auto.snapshot}{Internal use -- should be set to \code{TRUE} when this 50 | is an automatic snapshot.} 51 | 52 | \item{verbose}{Print output to the console while \code{snapshot}-ing?} 53 | 54 | \item{fallback.ok}{Fall back to the latest CRAN version of a package if the 55 | locally installed version is unavailable?} 56 | 57 | \item{snapshot.sources}{Download the tarball associated with a particular 58 | package?} 59 | 60 | \item{implicit.packrat.dependency}{Include \code{packrat} as an implicit 61 | dependency of this project, if not otherwise discovered? This should be 62 | \code{FALSE} only if you can guarantee that \code{packrat} will be available 63 | via other means when attempting to load this project.} 64 | 65 | \item{infer.dependencies}{If \code{TRUE}, infer package dependencies by 66 | examining the \R code.} 67 | } 68 | \description{ 69 | This is the internal implementation for \code{\link{snapshot}}. Most users 70 | should prefer calling \code{\link{snapshot}}. 71 | } 72 | \keyword{internal} 73 | -------------------------------------------------------------------------------- /man/status.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/status.R 3 | \name{status} 4 | \alias{status} 5 | \title{Show differences between the last snapshot and the library} 6 | \usage{ 7 | status(project = NULL, lib.loc = libDir(project), quiet = FALSE) 8 | } 9 | \arguments{ 10 | \item{project}{The directory that contains the R project.} 11 | 12 | \item{lib.loc}{The library to examine. Defaults to the private library 13 | associated with the project directory.} 14 | 15 | \item{quiet}{Print detailed information about the packrat status to the console?} 16 | } 17 | \value{ 18 | Either \code{NULL} if a \code{packrat} project has not yet been 19 | initialized, or a (invisibly) a \code{data.frame} with components: 20 | \item{package}{The package name,} 21 | \item{packrat.version}{The package version used in the last snapshot,} 22 | \item{packrat.source}{The location from which the package was obtained,} 23 | \item{library.version}{The package version available in the local library,} 24 | \item{currently.used}{Whether the package is used in any of the R code in the current project.} 25 | } 26 | \description{ 27 | Shows the differences between the project's packrat dependencies, its private 28 | package library, and its R scripts. 29 | } 30 | \details{ 31 | These differences are created when you use the normal R package management 32 | commands like \code{\link{install.packages}}, \code{\link{update.packages}}, 33 | and \code{\link{remove.packages}}. To bring these differences into packrat, you 34 | can use \code{\link{snapshot}}. 35 | 36 | Differences can also arise if one of your collaborators adds or removes 37 | packages from the packrat dependencies. In this case, you simply need to tell 38 | packrat to update your private package library using \code{\link{restore}}. 39 | } 40 | -------------------------------------------------------------------------------- /man/unbundle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bundle.R 3 | \name{unbundle} 4 | \alias{unbundle} 5 | \title{Unbundle a Packrat Project} 6 | \usage{ 7 | unbundle(bundle, where, ..., restore = TRUE) 8 | } 9 | \arguments{ 10 | \item{bundle}{Path to the bundled file.} 11 | 12 | \item{where}{The directory where we will unbundle the project.} 13 | 14 | \item{...}{Optional arguments passed to \code{\link{tar}}.} 15 | 16 | \item{restore}{Boolean; should we \code{\link{restore}} the library 17 | after \code{unbundle}-ing the project?} 18 | } 19 | \description{ 20 | Unbundle a previously \code{\link{bundle}}d project. 21 | } 22 | -------------------------------------------------------------------------------- /man/unused_packages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/packrat.R 3 | \name{unused_packages} 4 | \alias{unused_packages} 5 | \title{Find Unused Packages in a Project} 6 | \usage{ 7 | unused_packages(project = NULL, lib.loc = libDir(project)) 8 | } 9 | \arguments{ 10 | \item{project}{The project directory.} 11 | 12 | \item{lib.loc}{The library to check.} 13 | } 14 | \description{ 15 | Unused packages are those still contained within your project library, but 16 | are unused in your project. 17 | } 18 | -------------------------------------------------------------------------------- /packrat.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: 88c01d36-523a-49d0-b291-43c5007d3bf2 3 | 4 | RestoreWorkspace: No 5 | SaveWorkspace: No 6 | AlwaysSaveHistory: No 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: Sweave 14 | LaTeX: pdfLaTeX 15 | 16 | AutoAppendNewline: Yes 17 | StripTrailingWhitespace: Yes 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source --install-tests 22 | PackageCheckArgs: --as-cran 23 | PackageRoxygenize: rd,collate,namespace,vignette 24 | -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | checks 2 | library 3 | checks.noindex 4 | library.noindex 5 | cloud.noindex 6 | data.sqlite 7 | *.html 8 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Revdeps 2 | 3 | -------------------------------------------------------------------------------- /revdep/cran.md: -------------------------------------------------------------------------------- 1 | ## revdepcheck results 2 | 3 | We checked 5 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. :)* -------------------------------------------------------------------------------- /scenarios/git/scenario-git-1.R: -------------------------------------------------------------------------------- 1 | library(packrat) 2 | packratHome <- "~/git/packrat" 3 | setwd(packratHome) 4 | try(setwd("scenarios/git/"), silent = TRUE) 5 | source("../helper-scenarios.R") 6 | if (!grepl("scenarios/git", getwd(), fixed = TRUE)) { 7 | stop("Enter the 'scenarios/git/' directory before running this script") 8 | } 9 | projDir <- path.expand(file.path(packratHome, "scenarios", "git", "packrat-scenario-git-1")) 10 | mkdir(projDir) 11 | adamDir <- file.path(projDir, "adam") 12 | bettyDir <- file.path(projDir, "betty") 13 | repoDir <- file.path(projDir, "repo") 14 | repoGitDir <- file.path(repoDir, ".git") 15 | for (dir in c(adamDir, bettyDir, repoDir)) { 16 | unlink(dir, recursive = TRUE) 17 | mkdir(dir) 18 | } 19 | 20 | ## Initialize the repo dir and put it in a 'receiving' state 21 | setwd(repoDir) 22 | git("init") 23 | git("checkout -b empty") 24 | 25 | ## Initialize adam's packrat project 26 | setwd(adamDir) 27 | cat("library(digest)", file = "foo.R") 28 | git("init") 29 | init(enter = FALSE, source.packages = packratHome) 30 | 31 | ## Add everything and push to a remote 32 | git("add -A") 33 | git("commit -m 'initial commit'") 34 | git("remote add origin", repoGitDir) 35 | git("push --set-upstream origin master") 36 | 37 | ## Betty pulls to initialize her project 38 | setwd(bettyDir) 39 | git("clone", repoGitDir, ".") 40 | git("checkout master") 41 | packrat::on() # an init is forced now 42 | print(getNamespaceInfo("packrat", "path")) ## are we using the project local packrat? 43 | packrat::status() 44 | -------------------------------------------------------------------------------- /scenarios/helper-scenarios.R: -------------------------------------------------------------------------------- 1 | ## Initialize some directories 2 | mkdir <- function(path) 3 | dir.create(path, showWarnings = FALSE, recursive = TRUE) 4 | 5 | git <- function(...) { 6 | system(paste("git", ..., collapse = " ")) 7 | } 8 | 9 | normalize_path <- function(path) { 10 | normalizePath(path, winslash = "/", mustWork = FALSE) 11 | } 12 | -------------------------------------------------------------------------------- /tests/test-cranlike-repositories.R: -------------------------------------------------------------------------------- 1 | library(packrat) 2 | 3 | (function() { 4 | 5 | # Disable R_TESTS within this scope (we don't want the R 6 | # subprocess to attempt to call startup.Rs) 7 | R_TESTS <- Sys.getenv("R_TESTS", unset = NA) 8 | if (!is.na(R_TESTS)) { 9 | Sys.unsetenv("R_TESTS") 10 | on.exit(Sys.setenv(R_TESTS = R_TESTS), add = TRUE) 11 | } 12 | 13 | dir <- tempdir() 14 | owd <- setwd(dir) 15 | on.exit(setwd(owd), add = TRUE) 16 | 17 | # Save repos 18 | repos <- getOption("repos") 19 | on.exit(options(repos = repos), add = TRUE) 20 | 21 | # Create the local repo 22 | localCRAN <- file.path(dir, "sushi") 23 | packrat::repos_create(localCRAN) 24 | on.exit(unlink(localCRAN, recursive = TRUE), add = TRUE) 25 | 26 | # Use only the 'sushi' repository 27 | options(repos = getOption("repos")["sushi"]) 28 | 29 | # Create an example package. 30 | env <- new.env(parent = emptyenv()) 31 | env$sashimi <- function() {} 32 | suppressMessages( 33 | utils::package.skeleton("sashimi", path = dir, environment = env) 34 | ) 35 | on.exit(unlink(file.path(dir, "sashimi"), recursive = TRUE), add = TRUE) 36 | 37 | # tidy up the broken package 38 | unlink(file.path(dir, "sashimi/man"), recursive = TRUE) 39 | 40 | # Try uploading the package from the directory itself (requires building) 41 | message("\nBuilding sashimi:\n") 42 | packrat::repos_upload(file.path(dir, "sashimi"), "sushi") 43 | 44 | # Try building and uploading a tarball 45 | system(paste("R --vanilla CMD build", file.path(dir, "sashimi"))) 46 | tarball <- list.files(dir, pattern = "\\.tar\\.gz$")[[1]] 47 | packrat::repos_upload(file.path(dir, tarball), "sushi") 48 | 49 | # Try installing the package as normal 50 | tempLib <- file.path(dir, "library") 51 | if (!file.exists(tempLib)) { 52 | dir.create(tempLib) 53 | on.exit(unlink(tempLib, recursive = TRUE), add = TRUE) 54 | } 55 | install.packages("sashimi", lib = tempLib, type = "source") 56 | 57 | # avoid bogus warning from R CMD check 58 | eval(call("library", "sashimi", lib.loc = tempLib)) 59 | detach("package:sashimi", unload = TRUE) 60 | 61 | })() 62 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(packrat) 3 | 4 | test_check("packrat") 5 | -------------------------------------------------------------------------------- /tests/testthat/.gitignore: -------------------------------------------------------------------------------- 1 | repo 2 | repo-empty 3 | packages/packrat 4 | packrat/lib*/ 5 | -------------------------------------------------------------------------------- /tests/testthat/Ugly, but legal, path for a project (long)/bread/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: bread 2 | Type: Package 3 | Version: 1.0.0 4 | Repository: CRAN 5 | License: GPL 6 | Description: Packrat test package 7 | Title: Packrat test package 8 | Author: Anonymous Person 9 | Maintainer: Anonymous Person 10 | 11 | -------------------------------------------------------------------------------- /tests/testthat/Ugly, but legal, path for a project (long)/breakfast/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: breakfast 2 | Type: Package 3 | Version: 1.0.0 4 | Depends: oatmeal, toast 5 | Repository: CRAN 6 | License: GPL 7 | Description: Packrat test package 8 | Title: Packrat test package 9 | Author: Anonymous Person 10 | Maintainer: Anonymous Person 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testthat/Ugly, but legal, path for a project (long)/oatmeal/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: oatmeal 2 | Type: Package 3 | Version: 1.0.0 4 | Repository: CRAN 5 | License: GPL 6 | Description: Packrat test package 7 | Title: Packrat test package 8 | Author: Anonymous Person 9 | Maintainer: Anonymous Person 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/testthat/Ugly, but legal, path for a project (long)/packrat/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: packrat 2 | Type: Package 3 | Version: 0.0.0 4 | Repository: CRAN 5 | License: GPL 6 | Description: Packrat test package 7 | Title: Packrat test package 8 | Author: Anonymous Person 9 | Maintainer: Anonymous Person 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/testthat/Ugly, but legal, path for a project (long)/toast/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: toast 2 | Depends: bread 3 | Type: Package 4 | Version: 1.0.0 5 | Repository: CRAN 6 | License: GPL 7 | Description: Packrat test package 8 | Title: Packrat test package 9 | Author: Anonymous Person 10 | Maintainer: Anonymous Person 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/pkg.md: -------------------------------------------------------------------------------- 1 | # inferPackageRecord preserves fields: GitHub 2 | 3 | Code 4 | inferPackageRecord(df) 5 | Output 6 | $name 7 | [1] "pkg" 8 | 9 | $source 10 | [1] "github" 11 | 12 | $version 13 | [1] "0.1.0" 14 | 15 | $gh_repo 16 | [1] "plain_ol_pkg" 17 | 18 | $gh_username 19 | [1] "my-github-username" 20 | 21 | $gh_ref 22 | [1] "HEAD" 23 | 24 | $gh_sha1 25 | [1] "abc123" 26 | 27 | $remote_host 28 | [1] "api.github.com" 29 | 30 | $remote_repo 31 | [1] "plain_ol_pkg" 32 | 33 | $remote_username 34 | [1] "my-github-username" 35 | 36 | $remote_ref 37 | [1] "HEAD" 38 | 39 | $remote_sha 40 | [1] "abc123" 41 | 42 | attr(,"class") 43 | [1] "packageRecord" "github" 44 | 45 | # inferPackageRecord preserves fields: GitHub, pkg in subdir 46 | 47 | Code 48 | inferPackageRecord(df) 49 | Output 50 | $name 51 | [1] "pkginsubdir" 52 | 53 | $source 54 | [1] "github" 55 | 56 | $version 57 | [1] "0.1.0" 58 | 59 | $gh_repo 60 | [1] "pkg_in_subdir" 61 | 62 | $gh_username 63 | [1] "my-github-username" 64 | 65 | $gh_ref 66 | [1] "HEAD" 67 | 68 | $gh_sha1 69 | [1] "abc123" 70 | 71 | $gh_subdir 72 | [1] "pkginsubdir" 73 | 74 | $remote_host 75 | [1] "api.github.com" 76 | 77 | $remote_repo 78 | [1] "pkg_in_subdir" 79 | 80 | $remote_username 81 | [1] "my-github-username" 82 | 83 | $remote_ref 84 | [1] "HEAD" 85 | 86 | $remote_sha 87 | [1] "abc123" 88 | 89 | $remote_subdir 90 | [1] "pkginsubdir" 91 | 92 | attr(,"class") 93 | [1] "packageRecord" "github" 94 | 95 | # inferPackageRecord preserves fields: GitLab 96 | 97 | Code 98 | inferPackageRecord(df) 99 | Output 100 | $name 101 | [1] "pkg" 102 | 103 | $source 104 | [1] "gitlab" 105 | 106 | $version 107 | [1] "0.1.0" 108 | 109 | $remote_repo 110 | [1] "plain_ol_pkg" 111 | 112 | $remote_username 113 | [1] "my-gitlab-username" 114 | 115 | $remote_ref 116 | [1] "HEAD" 117 | 118 | $remote_sha 119 | [1] "abc123" 120 | 121 | $remote_host 122 | [1] "gitlab.com" 123 | 124 | attr(,"class") 125 | [1] "packageRecord" "gitlab" 126 | 127 | # inferPackageRecord preserves fields: GitLab, pkg in subdir 128 | 129 | Code 130 | inferPackageRecord(df) 131 | Output 132 | $name 133 | [1] "pkginsubdir" 134 | 135 | $source 136 | [1] "gitlab" 137 | 138 | $version 139 | [1] "0.1.0" 140 | 141 | $remote_repo 142 | [1] "pkg_in_subdir" 143 | 144 | $remote_username 145 | [1] "my-gitlab-username" 146 | 147 | $remote_ref 148 | [1] "HEAD" 149 | 150 | $remote_sha 151 | [1] "abc123" 152 | 153 | $remote_host 154 | [1] "gitlab.com" 155 | 156 | $remote_subdir 157 | [1] "pkginsubdir" 158 | 159 | attr(,"class") 160 | [1] "packageRecord" "gitlab" 161 | 162 | -------------------------------------------------------------------------------- /tests/testthat/lockfiles/lockfile-multipleRepos.txt: -------------------------------------------------------------------------------- 1 | PackratFormat: 1.3 2 | PackratVersion: 0.2.0.108 3 | RVersion: 3.2.0 4 | Repos: CRAN=https://cran.rstudio.org, 5 | BioCsoft=https://bioconductor.org/packages/3.0/bioc, 6 | BioCann=https://bioconductor.org/packages/3.0/data/annotation, 7 | BioCexp=https://bioconductor.org/packages/3.0/data/experiment, 8 | BioCextra=https://bioconductor.org/packages/3.0/extra 9 | 10 | 11 | Package: packrat 12 | Source: source 13 | Version: 0.2.0.108 14 | SourcePath: /Users/kevin/git/packrat 15 | -------------------------------------------------------------------------------- /tests/testthat/other-packages/packrat/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: packrat 2 | Type: Package 3 | Version: 0.0.0 4 | Repository: CRAN 5 | License: GPL 6 | Description: Packrat test package 7 | Title: Packrat test package 8 | Author: Anonymous Person 9 | Maintainer: Anonymous Person 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/testthat/packages/bread/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: bread 2 | Type: Package 3 | Version: 1.0.0 4 | Repository: CRAN 5 | License: GPL 6 | Description: Packrat test package 7 | Title: Packrat test package 8 | Author: Anonymous Person 9 | Maintainer: Anonymous Person 10 | 11 | -------------------------------------------------------------------------------- /tests/testthat/packages/breakfast/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: breakfast 2 | Type: Package 3 | Version: 1.0.0 4 | Depends: oatmeal, toast 5 | Repository: CRAN 6 | License: GPL 7 | Description: Packrat test package 8 | Title: Packrat test package 9 | Author: Anonymous Person 10 | Maintainer: Anonymous Person 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testthat/packages/egg/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: bread 2 | Type: Package 3 | Version: 1.0.0 4 | Repository: CRAN 5 | License: GPL 6 | Description: Packrat test package 7 | Title: Packrat test package 8 | Author: Anonymous Person 9 | Maintainer: Anonymous Person 10 | LinkingTo: yolk 11 | -------------------------------------------------------------------------------- /tests/testthat/packages/oatmeal/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: oatmeal 2 | Type: Package 3 | Version: 1.0.0 4 | Repository: CRAN 5 | License: GPL 6 | Description: Packrat test package 7 | Title: Packrat test package 8 | Author: Anonymous Person 9 | Maintainer: Anonymous Person 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/testthat/packages/toast/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: toast 2 | Depends: bread 3 | Type: Package 4 | Version: 1.0.0 5 | Repository: CRAN 6 | License: GPL 7 | Description: Packrat test package 8 | Title: Packrat test package 9 | Author: Anonymous Person 10 | Maintainer: Anonymous Person 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testthat/projects/carbs/flour.R: -------------------------------------------------------------------------------- 1 | library(bread) 2 | 3 | -------------------------------------------------------------------------------- /tests/testthat/projects/empty/empty.R: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rstudio/packrat/d88dfa39a344cd47ad2b31dcbf376a5c9a83d35a/tests/testthat/projects/empty/empty.R -------------------------------------------------------------------------------- /tests/testthat/projects/emptydesc/DESCRIPTION: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rstudio/packrat/d88dfa39a344cd47ad2b31dcbf376a5c9a83d35a/tests/testthat/projects/emptydesc/DESCRIPTION -------------------------------------------------------------------------------- /tests/testthat/projects/emptydesc/app.R: -------------------------------------------------------------------------------- 1 | # empty app.R 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/falsy-bitbucket/deps.R: -------------------------------------------------------------------------------- 1 | library(falsy) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/falsy-bitbucket/packrat/packrat.lock: -------------------------------------------------------------------------------- 1 | PackratFormat: 1.4 2 | PackratVersion: 0.5.0.11 3 | RVersion: 3.5.1 4 | Repos: CRAN=https://cran.rstudio.com/ 5 | 6 | Package: falsy 7 | Source: bitbucket 8 | Version: 1.0.1 9 | Hash: 97013d7da058d0be0595621449505494 10 | RemoteRepo: falsy 11 | RemoteUsername: rstudio_official 12 | RemoteRef: master 13 | RemoteSha: 26a36cf957a18569e311ef75b6f61f822de945ef 14 | RemoteHost: api.bitbucket.org/2.0 15 | -------------------------------------------------------------------------------- /tests/testthat/projects/falsy-gitlab/deps.R: -------------------------------------------------------------------------------- 1 | library(falsy) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/falsy-gitlab/packrat/packrat.lock: -------------------------------------------------------------------------------- 1 | PackratFormat: 1.4 2 | PackratVersion: 0.5.0.11 3 | RVersion: 3.5.1 4 | Repos: CRAN=https://cran.rstudio.com/ 5 | 6 | Package: falsy 7 | Source: gitlab 8 | Version: 1.0.1 9 | Hash: cd9f70fd26fa58a4b3070370b16b8660 10 | RemoteRepo: falsy 11 | RemoteUsername: jimhester 12 | RemoteRef: master 13 | RemoteSha: 26a36cf957a18569e311ef75b6f61f822de945ef 14 | RemoteHost: gitlab.com 15 | -------------------------------------------------------------------------------- /tests/testthat/projects/healthy/healthy.R: -------------------------------------------------------------------------------- 1 | library(oatmeal) 2 | 3 | -------------------------------------------------------------------------------- /tests/testthat/projects/libraries/library.R: -------------------------------------------------------------------------------- 1 | library(bread) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/libraries/packrat/lib/lib-current.R: -------------------------------------------------------------------------------- 1 | library(oatmeal) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/libraries/packrat/library.new/lib-new.R: -------------------------------------------------------------------------------- 1 | library(oatmeal) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/libraries/packrat/library.old/lib-old.R: -------------------------------------------------------------------------------- 1 | library(oatmeal) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/partlyignored/ignoreme/ignorethis.R: -------------------------------------------------------------------------------- 1 | library(toast) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/partlyignored/notignored.R: -------------------------------------------------------------------------------- 1 | library(bread) 2 | -------------------------------------------------------------------------------- /tests/testthat/projects/sated/sated.R: -------------------------------------------------------------------------------- 1 | library(breakfast) 2 | 3 | -------------------------------------------------------------------------------- /tests/testthat/projects/smallbreakfast/bread.R: -------------------------------------------------------------------------------- 1 | library(bread) 2 | 3 | -------------------------------------------------------------------------------- /tests/testthat/projects/smallbreakfast/oatmeal.R: -------------------------------------------------------------------------------- 1 | library(oatmeal) 2 | 3 | -------------------------------------------------------------------------------- /tests/testthat/resources/alternate-engines.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Untitled" 3 | output: html_document 4 | --- 5 | 6 | ```{bash} 7 | echo "Shell we play a game?" 8 | ``` 9 | 10 | ```{r} 11 | library(testthat) 12 | print("This code relies on testthat.") 13 | ``` 14 | 15 | ```{bash} 16 | echo "I shell return." 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /tests/testthat/resources/broken-chunks.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Rmd with broken chunks" 3 | runtime: shiny_prerendered 4 | --- 5 | 6 | This is an example document with broken chunks. 7 | 8 | ### OK 9 | 10 | ```{r} 11 | library(pkgA) 12 | library(pkgB) 13 | ``` 14 | 15 | 16 | ### Broken 17 | 18 | ```{r} 19 | library(pkgC) 20 | log(1 21 | ``` 22 | 23 | 24 | ### Not Broken 25 | 26 | ```{r} 27 | library(pkgD) 28 | ``` 29 | 30 | ### Also Broken 31 | 32 | ```{r} 33 | library(pkgE) 34 | log(1 35 | ``` 36 | 37 | ### OK 38 | 39 | ```{r} 40 | library(pkgF) 41 | library(pkgG) 42 | ``` 43 | -------------------------------------------------------------------------------- /tests/testthat/resources/dependencies.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: qmd with explicit package dependencies 3 | --- 4 | 5 | this qmd file has a package dependency in an r chunk. 6 | 7 | ```{r} 8 | library(bread) 9 | ``` 10 | -------------------------------------------------------------------------------- /tests/testthat/resources/descriptions/falsy.packrat: -------------------------------------------------------------------------------- 1 | Package: falsy 2 | Title: Define Truthy and Falsy Values 3 | Version: 1.0.1 4 | Authors@R: person("Gabor", "Csardi", , "csardi.gabor@gmail.com", role = 5 | c("aut", "cre")) 6 | Description: A value is falsy if it is NULL, FALSE, the empty string, 7 | zero, or an empty vector or list. Other values are truthy. The new 8 | %&&% and %||% operators work with falsy and truthy values and can 9 | be used for concise conditional execution. 10 | License: MIT + file LICENSE 11 | Suggests: testthat 12 | URL: https://github.com/gaborcsardi/falsy 13 | BugReports: https://github.com/gaborcsardi/falsy/issues 14 | NeedsCompilation: no 15 | Packaged: 2015-04-08 15:30:21 UTC; gaborcsardi 16 | Author: Gabor Csardi [aut, cre] 17 | Maintainer: Gabor Csardi 18 | Repository: CRAN 19 | Date/Publication: 2015-04-09 00:36:26 20 | GithubRepo: falsy 21 | GithubUsername: cran 22 | GithubRef: master 23 | GithubSHA1: 26a36cf957a18569e311ef75b6f61f822de945ef 24 | Built: R 3.4.4; ; 2019-06-17 18:35:06 UTC; unix 25 | InstallAgent: packrat 0.5.0.11 26 | InstallSource: github 27 | Hash: 463f9bedd8d616a3cdb766e6fb524100 28 | -------------------------------------------------------------------------------- /tests/testthat/resources/descriptions/falsy.remotes: -------------------------------------------------------------------------------- 1 | Package: falsy 2 | Title: Define Truthy and Falsy Values 3 | Version: 1.0.1 4 | Authors@R: person("Gabor", "Csardi", , "csardi.gabor@gmail.com", role = c("aut", "cre")) 5 | Description: A value is falsy if it is NULL, FALSE, the empty string, 6 | zero, or an empty vector or list. Other values are truthy. The new 7 | %&&% and %||% operators work with falsy and truthy values and 8 | can be used for concise conditional execution. 9 | License: MIT + file LICENSE 10 | Suggests: testthat 11 | URL: https://github.com/gaborcsardi/falsy 12 | BugReports: https://github.com/gaborcsardi/falsy/issues 13 | NeedsCompilation: no 14 | Packaged: 2019-06-18 13:40:33 UTC; aron 15 | Author: Gabor Csardi [aut, cre] 16 | Maintainer: Gabor Csardi 17 | Repository: CRAN 18 | Date/Publication: 2015-04-09 00:36:26 19 | RemoteType: github 20 | RemoteHost: api.github.com 21 | RemoteRepo: falsy 22 | RemoteUsername: cran 23 | RemoteRef: master 24 | RemoteSha: 26a36cf957a18569e311ef75b6f61f822de945ef 25 | GithubRepo: falsy 26 | GithubUsername: cran 27 | GithubRef: master 28 | GithubSHA1: 26a36cf957a18569e311ef75b6f61f822de945ef 29 | Built: R 3.5.1; ; 2019-06-18 13:40:33 UTC; unix 30 | -------------------------------------------------------------------------------- /tests/testthat/resources/descriptions/github: -------------------------------------------------------------------------------- 1 | Package: pkg 2 | Type: Package 3 | Title: Plain Old Package 4 | Version: 0.1.0 5 | Author: Toph Allen 6 | Maintainer: Toph Allen 7 | Description: This package is at the top level of its directory structure 8 | License: MIT 9 | Encoding: UTF-8 10 | RoxygenNote: 7.1.2 11 | RemoteType: github 12 | RemoteHost: api.github.com 13 | RemoteRepo: plain_ol_pkg 14 | RemoteUsername: my-github-username 15 | RemoteRef: HEAD 16 | RemoteSha: abc123 17 | GithubRepo: plain_ol_pkg 18 | GithubUsername: my-github-username 19 | GithubRef: HEAD 20 | GithubSHA1: abc123 21 | NeedsCompilation: no 22 | Packaged: 2023-02-22 17:15:10 UTC; root 23 | Built: R 4.2.1; ; 2023-02-22 17:15:10 UTC; unix 24 | -------------------------------------------------------------------------------- /tests/testthat/resources/descriptions/github_subdir: -------------------------------------------------------------------------------- 1 | Package: pkginsubdir 2 | Type: Package 3 | Title: Package In Subdirectory 4 | Version: 0.1.0 5 | Author: Toph Allen 6 | Maintainer: Toph Allen 7 | Description: This package lives in a subdirectory 8 | License: MIT 9 | Encoding: UTF-8 10 | RoxygenNote: 7.1.2 11 | RemoteType: github 12 | RemoteHost: api.github.com 13 | RemoteRepo: pkg_in_subdir 14 | RemoteUsername: my-github-username 15 | RemoteRef: HEAD 16 | RemoteSha: abc123 17 | RemoteSubdir: pkginsubdir 18 | GithubRepo: pkg_in_subdir 19 | GithubUsername: my-github-username 20 | GithubRef: HEAD 21 | GithubSHA1: abc123 22 | GithubSubdir: pkginsubdir 23 | NeedsCompilation: no 24 | Packaged: 2023-02-22 17:15:10 UTC; root 25 | Built: R 4.2.1; ; 2023-02-22 17:15:10 UTC; unix 26 | -------------------------------------------------------------------------------- /tests/testthat/resources/descriptions/gitlab: -------------------------------------------------------------------------------- 1 | Package: pkg 2 | Type: Package 3 | Title: Plain Old Package 4 | Version: 0.1.0 5 | Author: Toph Allen 6 | Maintainer: Toph Allen 7 | Description: This package is at the top level of its directory structure 8 | License: MIT 9 | Encoding: UTF-8 10 | RoxygenNote: 7.1.2 11 | RemoteType: gitlab 12 | RemoteHost: gitlab.com 13 | RemoteRepo: plain_ol_pkg 14 | RemoteUsername: my-gitlab-username 15 | RemoteRef: HEAD 16 | RemoteSha: abc123 17 | NeedsCompilation: no 18 | Packaged: 2023-02-22 17:15:10 UTC; root 19 | Built: R 4.2.1; ; 2023-02-22 17:15:10 UTC; unix 20 | -------------------------------------------------------------------------------- /tests/testthat/resources/descriptions/gitlab_subdir: -------------------------------------------------------------------------------- 1 | Package: pkginsubdir 2 | Type: Package 3 | Title: Package In Subdirectory 4 | Version: 0.1.0 5 | Author: Toph Allen 6 | Maintainer: Toph Allen 7 | Description: This package lives in a subdirectory 8 | License: MIT 9 | Encoding: UTF-8 10 | RoxygenNote: 7.1.2 11 | RemoteType: gitlab 12 | RemoteHost: gitlab.com 13 | RemoteRepo: pkg_in_subdir 14 | RemoteUsername: my-gitlab-username 15 | RemoteRef: HEAD 16 | RemoteSha: abc123 17 | RemoteSubdir: pkginsubdir 18 | NeedsCompilation: no 19 | Packaged: 2023-02-22 17:15:10 UTC; root 20 | Built: R 4.2.1; ; 2023-02-22 17:15:10 UTC; unix 21 | -------------------------------------------------------------------------------- /tests/testthat/resources/emoji.R: -------------------------------------------------------------------------------- 1 | # A package reference in a function argument default value. 2 | # https://github.com/rstudio/packrat/issues/630 3 | indirect <- function(x = emo::ji("see_no_evil")) { 4 | x 5 | } 6 | -------------------------------------------------------------------------------- /tests/testthat/resources/emoji.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "missing package reference" 3 | output: html_document 4 | --- 5 | 6 | `r emo::ji("see_no_evil")` 7 | -------------------------------------------------------------------------------- /tests/testthat/resources/evaluate-deps.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello, world! 3 | --- 4 | 5 | ```{r} 6 | library(abc) 7 | library(def) 8 | ``` 9 | 10 | ```{r eval=FALSE} 11 | x + {}} 12 | ``` 13 | 14 | ```{r} 15 | library(ghi) 16 | library(jkl) 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /tests/testthat/resources/interactive-doc-example.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Untitled" 3 | runtime: shiny 4 | output: html_document 5 | --- 6 | 7 | This R Markdown document is made interactive using Shiny. Unlike the more traditional workflow of creating static reports, you can now create documents that allow your readers to change the assumptions underlying your analysis and see the results immediately. 8 | 9 | To learn more, see [Interactive Documents](https://rmarkdown.rstudio.com/authoring_shiny.html). 10 | 11 | ## Inputs and Outputs 12 | 13 | You can embed Shiny inputs and outputs in your document. Outputs are automatically updated whenever inputs change. This demonstrates how a standard R plot can be made interactive by wrapping it in the Shiny `renderPlot` function. The `selectInput` and `sliderInput` functions create the input widgets used to drive the plot. 14 | 15 | ```{r, echo=FALSE} 16 | inputPanel( 17 | selectInput("n_breaks", label = "Number of bins:", 18 | choices = c(10, 20, 35, 50), selected = 20), 19 | 20 | sliderInput("bw_adjust", label = "Bandwidth adjustment:", 21 | min = 0.2, max = 2, value = 1, step = 0.2) 22 | ) 23 | 24 | renderPlot({ 25 | hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(input$n_breaks), 26 | xlab = "Duration (minutes)", main = "Geyser eruption duration") 27 | 28 | dens <- density(faithful$eruptions, adjust = input$bw_adjust) 29 | lines(dens, col = "blue") 30 | }) 31 | ``` 32 | 33 | ## Embedded Application 34 | 35 | It's also possible to embed an entire Shiny application within an R Markdown document using the `shinyAppDir` function. This example embeds a Shiny application located in another directory: 36 | 37 | ```{r, echo=FALSE} 38 | shinyAppDir( 39 | system.file("examples/06_tabsets", package="shiny"), 40 | options=list( 41 | width="100%", height=550 42 | ) 43 | ) 44 | ``` 45 | 46 | Note the use of the `height` parameter to determine how much vertical space the embedded application should occupy. 47 | 48 | You can also use the `shinyApp` function to define an application inline rather then in an external directory. 49 | 50 | In all of R code chunks above the `echo = FALSE` attribute is used. This is to prevent the R code within the chunk from rendering in the document alongside the Shiny components. 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /tests/testthat/resources/knitr-minimal.Rnw: -------------------------------------------------------------------------------- 1 | %% LyX 2.0.3 created this file. For more info, see https://www.lyx.org/. 2 | %% Do not edit unless you really know what you are doing. 3 | \documentclass{article} 4 | \usepackage[sc]{mathpazo} 5 | \usepackage[T1]{fontenc} 6 | \usepackage{geometry} 7 | \geometry{verbose,tmargin=2.5cm,bmargin=2.5cm,lmargin=2.5cm,rmargin=2.5cm} 8 | \setcounter{secnumdepth}{2} 9 | \setcounter{tocdepth}{2} 10 | \usepackage{url} 11 | \usepackage[unicode=true,pdfusetitle, 12 | bookmarks=true,bookmarksnumbered=true,bookmarksopen=true,bookmarksopenlevel=2, 13 | breaklinks=false,pdfborder={0 0 1},backref=false,colorlinks=false] 14 | {hyperref} 15 | \hypersetup{ 16 | pdfstartview={XYZ null null 1}} 17 | \begin{document} 18 | <>= 19 | library(knitr) 20 | # set global chunk options 21 | opts_chunk$set(fig.path='figure/minimal-', fig.align='center', fig.show='hold') 22 | options(replace.assign=TRUE,width=90) 23 | @ 24 | 25 | 26 | \title{A Minimal Demo of knitr} 27 | 28 | 29 | \author{Yihui Xie} 30 | 31 | \maketitle 32 | You can test if \textbf{knitr} works with this minimal demo. OK, let's 33 | get started with some boring random numbers: 34 | 35 | <>= 36 | set.seed(1121) 37 | (x=rnorm(20)) 38 | mean(x);var(x) 39 | @ 40 | 41 | The first element of \texttt{x} is \Sexpr{x[1]}. Boring boxplots 42 | and histograms recorded by the PDF device: 43 | 44 | <>= 45 | ## two plots side by side (option fig.show='hold') 46 | par(mar=c(4,4,.1,.1),cex.lab=.95,cex.axis=.9,mgp=c(2,.7,0),tcl=-.3,las=1) 47 | boxplot(x) 48 | hist(x,main='') 49 | @ 50 | 51 | Do the above chunks work? You should be able to compile the \TeX{} 52 | document and get a PDF file like this one: \url{https://bitbucket.org/stat/knitr/downloads/knitr-minimal.pdf}. 53 | The Rnw source of this document is at \url{https://github.com/yihui/knitr/blob/master/inst/examples/knitr-minimal.Rnw}. 54 | \end{document} 55 | -------------------------------------------------------------------------------- /tests/testthat/resources/loading-packages.R: -------------------------------------------------------------------------------- 1 | # Testcase inspired by 2 | # https://github.com/rstudio/packrat/issues/602 3 | # 4 | # Ignore the package argument to requireNamespace when it is a symbol. 5 | 6 | # This statement should produce a dependency, since library accepts 7 | # symbols as package names. 8 | library(bread) 9 | 10 | # This statement should produce a dependency, since we have a 11 | # literal string. 12 | requireNamespace("oatmeal") 13 | 14 | # These statements should not produce dependencies, since requireNamespace 15 | # does not accept symbols as package names and we have a symbol (pkg) as 16 | # input. 17 | wanted <- c("egg", "toast") 18 | missing <- lapply(wanted, function(pkg) { 19 | if (!requireNamespace(pkg, quietly = TRUE)) { 20 | pkg 21 | } 22 | }) 23 | 24 | # This statement should not produce dependencies, as we cannot read through 25 | # the pkg variable and symbols are not permitted with character.only = TRUE. 26 | pkg <- "breakfast" 27 | library(pkg, character.only = TRUE) 28 | -------------------------------------------------------------------------------- /tests/testthat/resources/no-chunks.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "No Chunks" 3 | output: html_document 4 | --- 5 | 6 | This R Markdown document does not have any chunks in it. It might as well be an 7 | ordinary Markdown document. 8 | -------------------------------------------------------------------------------- /tests/testthat/resources/params-example.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Rmd with parameters" 3 | params: 4 | whack: !r stringr::word("the quick brown fox jumped over the lazy dog", 2) 5 | --- 6 | 7 | This is an example document using parameters. 8 | 9 | ```{r} 10 | params$whack 11 | ``` 12 | -------------------------------------------------------------------------------- /tests/testthat/resources/simple.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: qmd without explicit package dependencies 3 | --- 4 | 5 | this is really just a markdown file. it has no explicit requirement on 6 | rmarkdown. 7 | -------------------------------------------------------------------------------- /tests/testthat/resources/test-sweave.Rnw: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | 3 | \begin{document} 4 | \SweaveOpts{concordance=TRUE} 5 | 6 | <<>>= 7 | library(digest) 8 | library(Rcpp) 9 | @ 10 | 11 | 12 | <<>>= 13 | @ 14 | 15 | \end{document} 16 | -------------------------------------------------------------------------------- /tests/testthat/resources/unknown-engines.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: A title. 3 | --- 4 | 5 | ```{unknown} 6 | an unknown engine 7 | ``` 8 | 9 | ```{r engine="mystery"} 10 | a mysterious engine 11 | ``` 12 | 13 | ```{Rscript} 14 | stop("don't run me") 15 | ``` 16 | -------------------------------------------------------------------------------- /tests/testthat/test-aaa.R: -------------------------------------------------------------------------------- 1 | test_that("we can re-initialize the test repositories", { 2 | skip_on_cran() 3 | rebuildTestRepo() 4 | rebuildEmptyTestRepo() 5 | }) 6 | -------------------------------------------------------------------------------- /tests/testthat/test-bitbucket.R: -------------------------------------------------------------------------------- 1 | bitbucket_pkg_record <- list( 2 | name = "museli", 3 | source = "bitbucket", 4 | version = "0.1.0", 5 | hash = "abc123", 6 | remote_repo = "museli", 7 | remote_username = "breakfaster", 8 | remote_ref = "HEAD", 9 | remote_sha = "abcde12345", 10 | remote_host = "api.bitbucket.org/2.0", 11 | depends = list() 12 | ) 13 | 14 | test_that("bitbucketArchiveUrl returns the correct URL", { 15 | mockery::stub(bitbucketArchiveUrl, "secureDownloadMethod", "curl") 16 | expect_equal( 17 | bitbucketArchiveUrl(bitbucket_pkg_record), 18 | "https://bitbucket.org/breakfaster/museli/get/abcde12345.tar.gz" 19 | ) 20 | }) 21 | 22 | test_that("bitbucketDownload calls renvDownload in the expected context", { 23 | url <- bitbucketArchiveUrl(bitbucket_pkg_record) 24 | destfile <- nullfile() 25 | 26 | # Testing the effect of the option, rather than just mocking canUseRenvDownload 27 | mockery::stub(bitbucketDownload, "canUseRenvDownload", TRUE) 28 | mockery::stub(bitbucketDownload, "bitbucketAuthenticated", TRUE) 29 | renv_download_mock <- mockery::mock(destfile) 30 | mockery::stub(bitbucketDownload, "renvDownload", renv_download_mock, depth = 5) 31 | 32 | bitbucketDownload(url, destfile) 33 | 34 | mockery::expect_called(renv_download_mock, 1) 35 | mockery::expect_args(renv_download_mock, 1, url, destfile, type = "bitbucket") 36 | }) 37 | 38 | test_that("bitbucketDownload calls bitbucketDownloadHttr in the expected context", { 39 | url <- bitbucketArchiveUrl(bitbucket_pkg_record) 40 | destfile <- nullfile() 41 | 42 | mockery::stub(bitbucketDownload, "bitbucketAuthenticated", TRUE) 43 | mockery::stub(bitbucketDownload, "canUseRenvDownload", FALSE) 44 | mockery::stub(bitbucketDownload, "canUseHttr", TRUE) 45 | httr_download_mock <- mockery::mock(TRUE) 46 | mockery::stub(bitbucketDownload, "bitbucketDownloadHttr", httr_download_mock, depth = 5) 47 | 48 | bitbucketDownload(url, destfile) 49 | 50 | mockery::expect_called(httr_download_mock, 1) 51 | mockery::expect_args(httr_download_mock, 1, url, destfile) 52 | }) 53 | 54 | test_that("bitbucketDownload calls downloadWithRetries in the expected contexts", { 55 | url <- bitbucketArchiveUrl(bitbucket_pkg_record) 56 | destfile <- nullfile() 57 | 58 | # With auth data but no configured auth-capable method configured 59 | 60 | mockery::stub(bitbucketDownload, "bitbucketAuthenticated", TRUE) 61 | mockery::stub(bitbucketDownload, "canUseRenvDownload", FALSE) 62 | mockery::stub(bitbucketDownload, "canUseHttr", FALSE) 63 | download_with_retries_mock <- mockery::mock(TRUE) 64 | mockery::stub(bitbucketDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) 65 | 66 | bitbucketDownload(url, destfile) 67 | 68 | mockery::expect_called(download_with_retries_mock, 1) 69 | mockery::expect_args(download_with_retries_mock, 1, url, destfile) 70 | 71 | # With auth-capable methods configured but no auth data 72 | 73 | mockery::stub(bitbucketDownload, "bitbucketAuthenticated", FALSE) 74 | mockery::stub(bitbucketDownload, "canUseRenvDownload", TRUE) 75 | mockery::stub(bitbucketDownload, "canUseHttr", TRUE) 76 | download_with_retries_mock <- mockery::mock(TRUE) 77 | mockery::stub(bitbucketDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) 78 | 79 | bitbucketDownload(url, destfile) 80 | 81 | mockery::expect_called(download_with_retries_mock, 1) 82 | mockery::expect_args(download_with_retries_mock, 1, url, destfile) 83 | }) 84 | -------------------------------------------------------------------------------- /tests/testthat/test-bundle.R: -------------------------------------------------------------------------------- 1 | test_that("Bundle works when using R's internal tar", { 2 | 3 | skip_on_cran() 4 | skip_on_travis() 5 | skip_on_ci() 6 | scopeTestContext() 7 | 8 | # force packrat to use the internal R tar 9 | TAR <- Sys.getenv("TAR") 10 | Sys.unsetenv("TAR") 11 | on.exit(Sys.setenv(TAR = TAR), add = TRUE) 12 | 13 | # bundle with the regular bundle and verify 14 | bundle_test(packrat::bundle, function() { 15 | expect_identical( 16 | grep("lib*", list.files("packrat"), value = TRUE, invert = TRUE), 17 | list.files("untarred/packrat-test-bundle/packrat/") 18 | ) 19 | }) 20 | 21 | }) 22 | 23 | test_that("Bundle works when omitting CRAN packages", { 24 | 25 | skip_on_cran() 26 | skip_on_travis() 27 | skip_on_ci() 28 | scopeTestContext() 29 | 30 | checker <- function() { 31 | # we shouldn't see any CRAN packages in the unbundled sources other than Packrat 32 | srcDir <- "untarred/packrat-test-bundle/packrat/src" 33 | srcFiles <- list.files(srcDir, pattern = "tar.gz$", recursive = TRUE) 34 | expect_true(length(srcFiles) == 1, "src dir should be empty (other than Packrat)") 35 | } 36 | 37 | bundle_test(packrat:::bundle, checker, omit.cran.src = TRUE) 38 | 39 | }) 40 | -------------------------------------------------------------------------------- /tests/testthat/test-cache.R: -------------------------------------------------------------------------------- 1 | # https://github.com/rstudio/packrat/issues/345 2 | test_that("package installation when configured with a a cache uses the cache", { 3 | skip_on_cran() 4 | skip_on_os("windows") 5 | 6 | scopeTestContext() 7 | 8 | projRoot <- cloneTestProject("healthy") 9 | libRoot <- file.path(projRoot, "packrat", "lib") 10 | srcRoot <- file.path(projRoot, "packrat", "src") 11 | 12 | theCache <- tempfile("packrat-cache-") 13 | ensureDirectory(theCache) 14 | Sys.setenv(R_PACKRAT_CACHE_DIR = theCache) 15 | on.exit(Sys.unsetenv("R_PACKRAT_CACHE_DIR"), add = TRUE) 16 | 17 | init(projRoot, options = list(local.repos = "packages"), enter = FALSE) 18 | 19 | rv <- R.Version() 20 | packageDir <- file.path(libDir(projRoot), "oatmeal") 21 | 22 | expect_true(file.exists(packageDir), packageDir) 23 | expect_false(is.symlink(packageDir), packageDir) 24 | 25 | set_opts(project = projRoot, use.cache = TRUE) 26 | on.exit(set_opts(use.cache = FALSE, project = projRoot), add = TRUE) 27 | 28 | options(packrat.verbose.cache = TRUE) 29 | on.exit(options(packrat.verbose.cache = FALSE), add = TRUE) 30 | 31 | # Initial restore. Populates the cache and creates a symlink into it. 32 | unlink(libRoot, recursive = TRUE) 33 | unlink(srcRoot, recursive = TRUE) 34 | restore(projRoot, 35 | overwrite.dirty = TRUE, 36 | prompt = FALSE, 37 | restart = FALSE) 38 | 39 | expect_true(file.exists(packageDir), packageDir) 40 | expect_true(is.symlink(packageDir), packageDir) 41 | 42 | # Subsequent restore. Uses the cache. 43 | unlink(libRoot, recursive = TRUE) 44 | unlink(srcRoot, recursive = TRUE) 45 | restore(projRoot, 46 | overwrite.dirty = TRUE, 47 | prompt = FALSE, 48 | restart = FALSE) 49 | 50 | # Daisy-chain a test where we attempt to recover when 51 | # a cache entry is corrupt. This test models some real-life 52 | # situations we've seen where a cache's package entries seem 53 | # to lose all files except for an empty DESCRIPTION. 54 | pkgDir <- file.path(libDir(projRoot), "oatmeal") 55 | cacheEntry <- system(paste("readlink", pkgDir), intern = TRUE) 56 | unlink(cacheEntry, recursive = TRUE) 57 | ensureDirectory(cacheEntry) 58 | file.create(file.path(cacheEntry, "DESCRIPTION")) 59 | 60 | unlink(libRoot, recursive = TRUE) 61 | unlink(srcRoot, recursive = TRUE) 62 | 63 | suppressWarnings( 64 | restore(projRoot, 65 | overwrite.dirty = TRUE, 66 | prompt = FALSE, 67 | restart = FALSE) 68 | ) 69 | 70 | expect_true(file.exists(packageDir), packageDir) 71 | expect_true(is.symlink(packageDir), packageDir) 72 | }) 73 | 74 | test_that("packrat uses the untrusted cache when instructed", { 75 | skip_on_cran() 76 | skip_on_os("windows") 77 | 78 | scopeTestContext() 79 | 80 | # pretend that we're Posit Connect 81 | Sys.setenv(POSIT_CONNECT = 1) 82 | on.exit(Sys.unsetenv("POSIT_CONNECT"), add = TRUE) 83 | 84 | projRoot <- cloneTestProject("healthy") 85 | libRoot <- file.path(projRoot, "packrat", "lib") 86 | srcRoot <- file.path(projRoot, "packrat", "src") 87 | 88 | theCache <- tempfile("packrat-cache-") 89 | ensureDirectory(theCache) 90 | Sys.setenv(R_PACKRAT_CACHE_DIR = theCache) 91 | on.exit(Sys.unsetenv("R_PACKRAT_CACHE_DIR"), add = TRUE) 92 | 93 | init(projRoot, options = list(local.repos = "packages"), enter = FALSE) 94 | 95 | rv <- R.Version() 96 | packageDir <- file.path(libDir(projRoot), "oatmeal") 97 | 98 | expect_true(file.exists(packageDir), packageDir) 99 | expect_false(is.symlink(packageDir), packageDir) 100 | 101 | set_opts(project = projRoot, use.cache = TRUE) 102 | on.exit(set_opts(use.cache = FALSE, project = projRoot), add = TRUE) 103 | 104 | options(packrat.verbose.cache = TRUE) 105 | on.exit(options(packrat.verbose.cache = FALSE), add = TRUE) 106 | 107 | # Initial restore. Populates the cache and creates a symlink into it. 108 | unlink(libRoot, recursive = TRUE) 109 | restore(projRoot, 110 | overwrite.dirty = TRUE, 111 | prompt = FALSE, 112 | restart = FALSE) 113 | 114 | expect_true(file.exists(packageDir), packageDir) 115 | expect_true(is.symlink(packageDir), packageDir) 116 | 117 | # Subsequent restore. Uses the cache. 118 | unlink(libRoot, recursive = TRUE) 119 | restore(projRoot, 120 | overwrite.dirty = TRUE, 121 | prompt = FALSE, 122 | restart = FALSE) 123 | 124 | expect_true(file.exists(packageDir), packageDir) 125 | expect_true(is.symlink(packageDir), packageDir) 126 | }) 127 | -------------------------------------------------------------------------------- /tests/testthat/test-downloader.R: -------------------------------------------------------------------------------- 1 | getAvailableDownloadMethods <- function() { 2 | 3 | if (is.windows()) { 4 | methods <- "internal" 5 | if (getRversion() >= "3.2") 6 | methods <- c(methods, "wininet") 7 | return(methods) 8 | } 9 | 10 | has <- function(program) { 11 | nzchar(Sys.which(program)[[1]]) 12 | } 13 | 14 | methods <- "internal" 15 | 16 | if (has("wget")) 17 | methods <- c(methods, "wget") 18 | 19 | if (has("curl")) 20 | methods <- c(methods, "curl") 21 | 22 | methods 23 | } 24 | 25 | test_that("404s are errors", { 26 | 27 | skip_on_cran() 28 | 29 | URL <- "https://cran.rstudio.com/no/such/file/here.txt" 30 | methods <- getAvailableDownloadMethods() 31 | 32 | destfile <- tempfile() 33 | on.exit(try(unlink(file), silent = TRUE), add = TRUE) 34 | 35 | for (method in methods) { 36 | expect_error( 37 | downloadFile(URL, destfile = destfile, method = method, quiet = TRUE), 38 | info = sprintf("(method = '%s')", method) 39 | ) 40 | } 41 | 42 | }) 43 | 44 | test_that("The same content is returned regardless of download method", { 45 | skip_on_cran() 46 | 47 | URL <- "https://cran.rstudio.org/src/base/AUTHORS" 48 | methods <- getAvailableDownloadMethods() 49 | methods <- setdiff(methods, "internal") 50 | 51 | contents <- lapply(methods, function(method) { 52 | 53 | path <- tempfile() 54 | on.exit(try(unlink(path), silent = TRUE), add = TRUE) 55 | 56 | downloadFile(URL, destfile = path, method = method, quiet = TRUE) 57 | readChar(path, file.info(path)$size, TRUE) 58 | 59 | }) 60 | 61 | expect_true( 62 | length(Reduce(unique, contents)) == 1, 63 | info = "various download methods retrieve exact same content" 64 | ) 65 | 66 | }) 67 | 68 | test_that("renvDownload calls renv$download, passing in the values it received", { 69 | url <- "https://github.com/my-great-org/cool-repo.tar.gz" 70 | destfile <- nullfile() 71 | type <- "github" 72 | 73 | renv_download_mock <- mockery::mock(destfile) 74 | mockery::stub(renvDownload, "renv$download", renv_download_mock) 75 | 76 | renvDownload(url, destfile, type = type) 77 | 78 | mockery::expect_called(renv_download_mock, 1) 79 | mockery::expect_args(renv_download_mock, 1, url, destfile, type) 80 | }) 81 | 82 | test_that("authDownloadAdvice offers sound advice", { 83 | 84 | # Using renv for downloads 85 | expect_true(grepl("Packrat is configured to use internal renv for authenticated downloads.", authDownloadAdvice("github", TRUE, "renv")(), fixed = TRUE)) 86 | 87 | # Using httr for downloads 88 | expect_true(grepl("Packrat will use the httr package for authenticated downloads.", authDownloadAdvice("gitlab", TRUE, "httr")(), fixed = TRUE)) 89 | 90 | # With no available auth methods 91 | expect_true(grepl("Packrat is not configured to use an auth-capable download method. Try setting the option packrat.authenticated.downloads.use.renv to TRUE, or installing the httr package.", authDownloadAdvice("bitbucket", TRUE, "internal")(), fixed = TRUE)) 92 | 93 | # Expected auth token (GitHub) present 94 | expect_true(grepl("GITHUB_PAT found; check that it is correct.", authDownloadAdvice("github", TRUE, "renv")(), fixed = TRUE)) 95 | 96 | # Expected token not found 97 | expect_true(grepl("BITBUCKET_USERNAME and BITBUCKET_PASSWORD environment variables not found.", authDownloadAdvice("bitbucket", FALSE, "httr")(), fixed = TRUE)) 98 | }) 99 | -------------------------------------------------------------------------------- /tests/testthat/test-env.R: -------------------------------------------------------------------------------- 1 | test_that("TAR environment variable is respected", { 2 | TAR <- Sys.getenv("TAR") 3 | if (is.na(TAR)) { 4 | on.exit(Sys.unsetenv("TAR")) 5 | } else { 6 | on.exit(Sys.setenv("TAR" = TAR)) 7 | } 8 | 9 | Sys.setenv(TAR = "/foo/bar/tar") 10 | 11 | expect_equal(tar_binary(), "/foo/bar/tar") 12 | }) 13 | 14 | test_that("On Unix, use tar on the path if it exists", { 15 | TAR <- Sys.getenv("TAR") 16 | if (is.na(TAR)) { 17 | on.exit(Sys.unsetenv("TAR")) 18 | } else { 19 | on.exit(Sys.setenv("TAR" = TAR)) 20 | } 21 | 22 | Sys.unsetenv("TAR") 23 | 24 | mockery::stub(tar_binary, "is.unix", TRUE) 25 | mockery::stub(tar_binary, "is.windows", FALSE) 26 | mockery::stub(tar_binary, "Sys.which", "/foo/bar/tar") 27 | mockery::stub(tar_binary, "file.exists", TRUE) 28 | 29 | expect_equal(tar_binary(), "/foo/bar/tar") 30 | }) 31 | 32 | test_that("On Unix, use 'internal' as a fallback if no tar is found on the PATH", { 33 | TAR <- Sys.getenv("TAR") 34 | if (is.na(TAR)) { 35 | on.exit(Sys.unsetenv("TAR")) 36 | } else { 37 | on.exit(Sys.setenv("TAR" = TAR)) 38 | } 39 | 40 | Sys.unsetenv("TAR") 41 | 42 | mockery::stub(tar_binary, "is.unix", TRUE) 43 | mockery::stub(tar_binary, "is.windows", FALSE) 44 | mockery::stub(tar_binary, "Sys.which", "") 45 | 46 | expect_warning(expect_equal(tar_binary(), "internal")) 47 | }) 48 | 49 | test_that("On Windows, use the system tar if it exists", { 50 | TAR <- Sys.getenv("TAR") 51 | if (is.na(TAR)) { 52 | on.exit(Sys.unsetenv("TAR")) 53 | } else { 54 | on.exit(Sys.setenv("TAR" = TAR)) 55 | } 56 | 57 | Sys.unsetenv("TAR") 58 | 59 | fake_sys_getenv <- function(x, ...) { 60 | if (x == "TAR") { 61 | return(NA) 62 | } else if (x == "SystemRoot") { 63 | return("C:/foo") 64 | } 65 | } 66 | 67 | mockery::stub(tar_binary, "is.unix", FALSE) 68 | mockery::stub(tar_binary, "is.windows", TRUE) 69 | mockery::stub(tar_binary, "Sys.getenv", fake_sys_getenv) 70 | mockery::stub(tar_binary, "file.path", "C:/foo/tar.exe") 71 | mockery::stub(tar_binary, "file.exists", TRUE) 72 | 73 | expect_equal(tar_binary(), "C:/foo/tar.exe") 74 | }) 75 | 76 | test_that("On Windows, use 'internal' as a fallback if system tar doesn't exist", { 77 | TAR <- Sys.getenv("TAR") 78 | if (is.na(TAR)) { 79 | on.exit(Sys.unsetenv("TAR")) 80 | } else { 81 | on.exit(Sys.setenv("TAR" = TAR)) 82 | } 83 | 84 | Sys.unsetenv("TAR") 85 | 86 | fake_sys_getenv <- function(x, ...) { 87 | if (x == "TAR") { 88 | return(NA) 89 | } else if (x == "SystemRoot") { 90 | return("C:/foo") 91 | } 92 | } 93 | 94 | mockery::stub(tar_binary, "is.unix", FALSE) 95 | mockery::stub(tar_binary, "is.windows", TRUE) 96 | mockery::stub(tar_binary, "Sys.getenv", fake_sys_getenv) 97 | mockery::stub(tar_binary, "file.path", "C:/foo/tar.exe") 98 | mockery::stub(tar_binary, "file.exists", FALSE) 99 | 100 | expect_warning(expect_equal(tar_binary(), "internal")) 101 | }) 102 | -------------------------------------------------------------------------------- /tests/testthat/test-git.R: -------------------------------------------------------------------------------- 1 | test_that("isGitProject identifies projects as sub-directories of git-managed folders as git projects", { 2 | skip_on_cran() 3 | 4 | dir <- file.path(tempdir(), "test-packrat-git") 5 | subdir <- file.path(dir, "subdir") 6 | dir.create(subdir, recursive = TRUE) 7 | dir.create(file.path(dir, ".git")) 8 | expect_true(isGitProject(dir)) 9 | expect_true(isGitProject(subdir)) 10 | expect_false(isGitProject(tempdir())) 11 | unlink(dir, recursive = TRUE) 12 | 13 | }) 14 | -------------------------------------------------------------------------------- /tests/testthat/test-github.R: -------------------------------------------------------------------------------- 1 | github_pkg_record <- list( 2 | name = "muesli", 3 | source = "github", 4 | version = "0.1.0", 5 | hash = "abc123", 6 | gh_repo = "muesli", 7 | gh_username = "breakfaster", 8 | gh_ref = "HEAD", 9 | gh_sha1 = "abcde12345", 10 | remote_host = "api.github.com", 11 | remote_repo = "muesli", 12 | remote_username = "breakfaster", 13 | remote_ref = "HEAD", 14 | remote_sha = "abcde12345", 15 | depends = list() 16 | ) 17 | 18 | old_github_pkg_record <- list( 19 | name = "muesli", 20 | source = "github", 21 | version = "0.1.0", 22 | hash = "abc123", 23 | gh_repo = "muesli", 24 | gh_username = "breakfaster", 25 | gh_ref = "HEAD", 26 | gh_sha1 = "abcde12345", 27 | depends = list() 28 | ) 29 | 30 | 31 | test_that("githubArchiveUrl returns the correct URL", { 32 | mockery::stub(githubArchiveUrl, "secureDownloadMethod", "curl") 33 | expect_equal( 34 | githubArchiveUrl(github_pkg_record), 35 | "https://api.github.com/repos/breakfaster/muesli/tarball/abcde12345" 36 | ) 37 | 38 | expect_equal( 39 | githubArchiveUrl(old_github_pkg_record), 40 | "https://api.github.com/repos/breakfaster/muesli/tarball/abcde12345" 41 | ) 42 | }) 43 | 44 | test_that("githubDownload calls renvDownload in the expected context", { 45 | url <- githubArchiveUrl(github_pkg_record) 46 | destfile <- nullfile() 47 | 48 | # Testing the effect of the option, rather than just mocking canUseRenvDownload 49 | mockery::stub(githubDownload, "canUseRenvDownload", TRUE) 50 | mockery::stub(githubDownload, "githubAuthenticated", TRUE) 51 | renv_download_mock <- mockery::mock(destfile) 52 | mockery::stub(githubDownload, "renvDownload", renv_download_mock, depth = 5) 53 | 54 | githubDownload(url, destfile) 55 | 56 | mockery::expect_called(renv_download_mock, 1) 57 | mockery::expect_args(renv_download_mock, 1, url, destfile, type = "github") 58 | }) 59 | 60 | test_that("githubDownload calls githubDownloadHttr in the expected context", { 61 | url <- githubArchiveUrl(github_pkg_record) 62 | destfile <- nullfile() 63 | 64 | mockery::stub(githubDownload, "githubAuthenticated", TRUE) 65 | mockery::stub(githubDownload, "canUseRenvDownload", FALSE) 66 | mockery::stub(githubDownload, "canUseHttr", TRUE) 67 | httr_download_mock <- mockery::mock(TRUE) 68 | mockery::stub(githubDownload, "githubDownloadHttr", httr_download_mock, depth = 5) 69 | 70 | githubDownload(url, destfile) 71 | 72 | mockery::expect_called(httr_download_mock, 1) 73 | mockery::expect_args(httr_download_mock, 1, url, destfile) 74 | }) 75 | 76 | test_that("githubDownload calls downloadWithRetries in the expected contexts", { 77 | url <- githubArchiveUrl(github_pkg_record) 78 | destfile <- nullfile() 79 | 80 | # With auth data but no configured auth-capable method configured 81 | 82 | mockery::stub(githubDownload, "githubAuthenticated", TRUE) 83 | mockery::stub(githubDownload, "canUseRenvDownload", FALSE) 84 | mockery::stub(githubDownload, "canUseHttr", FALSE) 85 | download_with_retries_mock <- mockery::mock(TRUE) 86 | mockery::stub(githubDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) 87 | 88 | githubDownload(url, destfile) 89 | 90 | mockery::expect_called(download_with_retries_mock, 1) 91 | mockery::expect_args(download_with_retries_mock, 1, url, destfile) 92 | 93 | # With auth-capable methods configured but no auth data 94 | 95 | mockery::stub(githubDownload, "githubAuthenticated", FALSE) 96 | mockery::stub(githubDownload, "canUseRenvDownload", TRUE) 97 | mockery::stub(githubDownload, "canUseHttr", TRUE) 98 | download_with_retries_mock <- mockery::mock(TRUE) 99 | mockery::stub(githubDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) 100 | 101 | githubDownload(url, destfile) 102 | 103 | mockery::expect_called(download_with_retries_mock, 1) 104 | mockery::expect_args(download_with_retries_mock, 1, url, destfile) 105 | }) 106 | -------------------------------------------------------------------------------- /tests/testthat/test-gitlab.R: -------------------------------------------------------------------------------- 1 | gitlab_pkg_record <- list( 2 | name = "museli", 3 | source = "gitlab", 4 | version = "0.1.0", 5 | hash = "abc123", 6 | remote_repo = "museli", 7 | remote_username = "breakfaster", 8 | remote_ref = "HEAD", 9 | remote_sha = "abcde12345", 10 | remote_host = "gitlab.com", 11 | depends = list() 12 | ) 13 | 14 | gitlab_subgroup_pkg_record <- list( 15 | name = "museli", 16 | source = "gitlab", 17 | version = "0.1.0", 18 | hash = "abc123", 19 | remote_repo = "museli/strawberries", 20 | remote_username = "breakfaster", 21 | remote_ref = "HEAD", 22 | remote_sha = "abcde12345", 23 | remote_host = "gitlab.com", 24 | depends = list() 25 | ) 26 | 27 | test_that("gitlabArchiveUrl returns the correct URL", { 28 | mockery::stub(gitlabArchiveUrl, "secureDownloadMethod", "curl") 29 | expect_equal( 30 | gitlabArchiveUrl(gitlab_pkg_record), 31 | "https://gitlab.com/api/v4/projects/breakfaster%2Fmuseli/repository/archive?sha=abcde12345" 32 | ) 33 | expect_equal( 34 | gitlabArchiveUrl(gitlab_subgroup_pkg_record), 35 | "https://gitlab.com/api/v4/projects/breakfaster%2Fmuseli%2Fstrawberries/repository/archive?sha=abcde12345" 36 | ) 37 | }) 38 | 39 | test_that("gitlabDownload calls renvDownload in the expected context", { 40 | url <- gitlabArchiveUrl(gitlab_pkg_record) 41 | destfile <- nullfile() 42 | 43 | # Testing the effect of the option, rather than just mocking canUseRenvDownload 44 | mockery::stub(gitlabDownload, "canUseRenvDownload", TRUE) 45 | mockery::stub(gitlabDownload, "gitlabAuthenticated", TRUE) 46 | renv_download_mock <- mockery::mock(destfile) 47 | mockery::stub(gitlabDownload, "renvDownload", renv_download_mock, depth = 5) 48 | 49 | gitlabDownload(url, destfile) 50 | 51 | mockery::expect_called(renv_download_mock, 1) 52 | mockery::expect_args(renv_download_mock, 1, url, destfile, type = "gitlab") 53 | }) 54 | 55 | test_that("gitlabDownload calls gitlabDownloadHttr in the expected context", { 56 | url <- gitlabArchiveUrl(gitlab_pkg_record) 57 | destfile <- nullfile() 58 | 59 | mockery::stub(gitlabDownload, "gitlabAuthenticated", TRUE) 60 | mockery::stub(gitlabDownload, "canUseRenvDownload", FALSE) 61 | mockery::stub(gitlabDownload, "canUseHttr", TRUE) 62 | httr_download_mock <- mockery::mock(TRUE) 63 | mockery::stub(gitlabDownload, "gitlabDownloadHttr", httr_download_mock, depth = 5) 64 | 65 | gitlabDownload(url, destfile) 66 | 67 | mockery::expect_called(httr_download_mock, 1) 68 | mockery::expect_args(httr_download_mock, 1, url, destfile) 69 | }) 70 | 71 | test_that("gitlabDownload calls downloadWithRetries in the expected contexts", { 72 | url <- gitlabArchiveUrl(gitlab_pkg_record) 73 | destfile <- nullfile() 74 | 75 | # With auth data but no configured auth-capable method configured 76 | 77 | mockery::stub(gitlabDownload, "gitlabAuthenticated", TRUE) 78 | mockery::stub(gitlabDownload, "canUseRenvDownload", FALSE) 79 | mockery::stub(gitlabDownload, "canUseHttr", FALSE) 80 | download_with_retries_mock <- mockery::mock(TRUE) 81 | mockery::stub(gitlabDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) 82 | 83 | gitlabDownload(url, destfile) 84 | 85 | mockery::expect_called(download_with_retries_mock, 1) 86 | mockery::expect_args(download_with_retries_mock, 1, url, destfile) 87 | 88 | # With auth-capable methods configured but no auth data 89 | 90 | mockery::stub(gitlabDownload, "gitlabAuthenticated", FALSE) 91 | mockery::stub(gitlabDownload, "canUseRenvDownload", TRUE) 92 | mockery::stub(gitlabDownload, "canUseHttr", TRUE) 93 | download_with_retries_mock <- mockery::mock(TRUE) 94 | mockery::stub(gitlabDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) 95 | 96 | gitlabDownload(url, destfile) 97 | 98 | mockery::expect_called(download_with_retries_mock, 1) 99 | mockery::expect_args(download_with_retries_mock, 1, url, destfile) 100 | }) 101 | -------------------------------------------------------------------------------- /tests/testthat/test-hash.R: -------------------------------------------------------------------------------- 1 | test_that("we can hash packages containing multiple packages in LinkingTo", { 2 | skip_on_cran() 3 | 4 | path <- system.file("DESCRIPTION", package = "Rclusterpp") 5 | if (file.exists(path)) { 6 | hash(path) 7 | } 8 | }) 9 | 10 | test_that("hash function is available and has expected arguments", { 11 | skip_on_cran() 12 | 13 | # This test is a canary that you may be breaking compatibility with Connect, 14 | # which expects this non-exported function to be present. That's not to say 15 | # the function signature can't be changed, only that the relevant call in 16 | # Connect's packrat_restore.R should be studied to avoid any breakage. 17 | 18 | 19 | expect_identical( 20 | formals(hash), 21 | pairlist( 22 | path = quote(expr =), # nolint: infix_spaces_linter. r-lib/lintr#1889 23 | descLookup = as.name("installedDescLookup") 24 | ) 25 | ) 26 | 27 | }) 28 | 29 | test_that("hash treats some RemoteType values as CRAN", { 30 | # DESCRIPTION as created by install.packages 31 | simpleDescription <- tempfile() 32 | on.exit(unlink(simpleDescription), add = TRUE) 33 | writeLines(c( 34 | "Package: dummy", 35 | "Version: 1.0.0" 36 | ), simpleDescription) 37 | simpleHash <- hash(simpleDescription) 38 | 39 | cranDescription <- tempfile() 40 | on.exit(unlink(cranDescription), add = TRUE) 41 | writeLines(c( 42 | "Package: dummy", 43 | "Version: 1.0.0", 44 | "RemoteType: cran" 45 | ), cranDescription) 46 | cranHash <- hash(cranDescription) 47 | expect_equal(cranHash, simpleHash) 48 | 49 | standardDescription <- tempfile() 50 | on.exit(unlink(standardDescription), add = TRUE) 51 | writeLines(c( 52 | "Package: dummy", 53 | "Version: 1.0.0", 54 | "RemoteType: standard" 55 | ), standardDescription) 56 | standardHash <- hash(standardDescription) 57 | expect_equal(standardHash, simpleHash) 58 | 59 | urlDescription <- tempfile() 60 | on.exit(unlink(urlDescription), add = TRUE) 61 | writeLines(c( 62 | "Package: dummy", 63 | "Version: 1.0.0", 64 | "RemoteType: url", 65 | "RemoteUrl: https://cran.rstudio.com//src/contrib/Archive/dummy/dummy_1.1.0.tar.gz" 66 | ), urlDescription) 67 | urlHash <- hash(urlDescription) 68 | expect_equal(urlHash, simpleHash) 69 | }) 70 | -------------------------------------------------------------------------------- /tests/testthat/test-ignores.R: -------------------------------------------------------------------------------- 1 | test_that("updateRBuildIgnore adds the packrat directory to ignore", { 2 | path <- file.path(tempdir(), ".Rbuildignore") 3 | unlink(path) 4 | updateRBuildIgnore(project = tempdir()) 5 | content <- readLines(path) 6 | expect_identical(content, c("^packrat/", "^\\.Rprofile$")) 7 | unlink(path) 8 | }) 9 | 10 | test_that("updateRBuildIgnore preserves content in ignore file", { 11 | path <- file.path(tempdir(), ".Rbuildignore") 12 | unlink(path) 13 | cat(c("foo", "bar", "baz"), file = path, sep = "\n") 14 | updateRBuildIgnore(project = tempdir()) 15 | content <- readLines(path) 16 | expect_identical(content, c("foo", "bar", "baz", "^packrat/", "^\\.Rprofile$")) 17 | unlink(path) 18 | }) 19 | 20 | test_that("updateGitIgnore works", { 21 | 22 | options <- list( 23 | vcs.ignore.lib = TRUE, 24 | vcs.ignore.src = FALSE 25 | ) 26 | dir <- file.path(tempdir(), "packrat-test") 27 | .gitignore <- file.path(dir, ".gitignore") 28 | dir.create(dir) 29 | updateGitIgnore(project = dir, options = options) 30 | content <- readLines(.gitignore) 31 | expect_identical(content, "packrat/lib*/") 32 | 33 | ## idempotency 34 | updateGitIgnore(project = dir, options = options) 35 | content <- readLines(.gitignore) 36 | expect_identical(content, "packrat/lib*/") 37 | 38 | ## preserve content of a .gitignore 39 | unlink(.gitignore) 40 | cat(c("foo", "bar", "baz"), file = .gitignore, sep = "\n") 41 | updateGitIgnore(project = dir, options = options) 42 | content <- readLines(.gitignore) 43 | expect_true(all(c("foo", "bar", "baz", "packrat/lib*/") %in% content)) 44 | 45 | ## change options 46 | options$vcs.ignore.src <- TRUE 47 | updateGitIgnore(project = dir, options = options) 48 | content <- readLines(.gitignore) 49 | expect_true(all(c("foo", "bar", "baz", "packrat/lib*/", "packrat/src/") %in% content)) 50 | 51 | ## remove all options 52 | options[] <- FALSE 53 | updateGitIgnore(project = dir, options = options) 54 | content <- readLines(.gitignore) 55 | expect_true(all(c("foo", "bar", "baz") %in% content)) 56 | expect_false("packrat/lib*/" %in% content) 57 | expect_false("packrat/src/" %in% content) 58 | 59 | ## when all options FALSE and .gitignore does not already 60 | ## exist, .gitignore is not created. 61 | unlink(.gitignore) 62 | updateGitIgnore(project = dir, options = options) 63 | expect_false(file.exists(.gitignore)) 64 | 65 | unlink(dir, recursive = TRUE) 66 | 67 | }) 68 | 69 | test_that("updateIgnoreFile preserves old structure of file", { 70 | 71 | contents <- c( 72 | "# This is a comment.", 73 | "ignore/path", 74 | "", 75 | "# This is a comment.", 76 | "ignore/path" 77 | ) 78 | 79 | file <- tempfile() 80 | on.exit(unlink(file)) 81 | cat(contents, file = file, sep = "\n") 82 | 83 | updateIgnoreFile(project = tempdir(), file = basename(file), add = c("packrat/lib*/")) 84 | updated <- readLines(file) 85 | expect_identical(updated, c(contents, "packrat/lib*/")) 86 | 87 | }) 88 | -------------------------------------------------------------------------------- /tests/testthat/test-local-repositories.R: -------------------------------------------------------------------------------- 1 | withTestContext({ 2 | 3 | test_that("init fails when package not found in any repo", { 4 | projRoot <- cloneTestProject("sated") 5 | repos <- getOption("repos") 6 | options(repos = c(CRAN = paste0("file:///", normalizePath("repo-empty")))) 7 | ## we expect a warning signalling that the package 'breakfast' is not found 8 | ## in a repo or locally 9 | expect_error(suppressWarnings(init(enter = FALSE, projRoot))) 10 | options(repos = repos) 11 | }) 12 | 13 | test_that("install_local fails if no repository has been defined", { 14 | expect_error(install_local("foo")) 15 | }) 16 | 17 | test_that("packrat::get_opts can read / write atrocious paths", { 18 | 19 | path <- list.files(pattern = "^Ugly") 20 | with_dir(tempdir(), { 21 | opts$local.repos(path) 22 | readPath <- opts$local.repos() 23 | expect_identical(path, readPath) 24 | }) 25 | }) 26 | 27 | }) 28 | -------------------------------------------------------------------------------- /tests/testthat/test-lockfile.R: -------------------------------------------------------------------------------- 1 | test_that("Topo sort works", { 2 | 3 | # Good 4 | graph <- list( 5 | 'A' = c('B', 'C'), 6 | 'B' = c(), 7 | 'C' = c('B'), 8 | 'D' = c() 9 | ) 10 | expect_true(verifyTopoSort(graph, topoSort(graph))) 11 | 12 | # Bad: Circular graph 13 | bad.graph <- list( 14 | 'A' = c('B'), 15 | 'B' = c('C'), 16 | 'C' = c('A') 17 | ) 18 | expect_error(topoSort(bad.graph)) 19 | 20 | # Bad: Dependency that has no row 21 | bad.graph.2 <- list( 22 | 'A' = c('D') 23 | ) 24 | expect_error(topoSort(bad.graph.2)) 25 | }) 26 | 27 | test_that("Repository is properly split by readLockFile", { 28 | 29 | lf <- readLockFile("lockfiles/lockfile-multipleRepos.txt") 30 | expect_equal( 31 | lf$repos, 32 | c(CRAN = "https://cran.rstudio.org", 33 | BioCsoft = "https://bioconductor.org/packages/3.0/bioc", 34 | BioCann = "https://bioconductor.org/packages/3.0/data/annotation", 35 | BioCexp = "https://bioconductor.org/packages/3.0/data/experiment", 36 | BioCextra = "https://bioconductor.org/packages/3.0/extra" 37 | ) 38 | ) 39 | 40 | }) 41 | -------------------------------------------------------------------------------- /tests/testthat/test-options.R: -------------------------------------------------------------------------------- 1 | withTestContext({ 2 | # Confirms that we can use set_opts and the single-option setter and that the 3 | # single-option setter does not overwrite previously configured state (#655) 4 | test_that("an option can be set and retrieved", { 5 | projRoot <- cloneTestProject("empty") 6 | 7 | owd <- setwd(projRoot) 8 | on.exit(setwd(owd)) 9 | 10 | packrat::set_opts(ignored.packages = c("emo"), persist = FALSE) 11 | packrat::opts$snapshot.recommended.packages(TRUE, persist = FALSE) 12 | 13 | expect_equal(get_opts("ignored.packages"), c("emo")) 14 | expect_equal(get_opts("snapshot.recommended.packages"), TRUE) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /tests/testthat/test-packrat-mode.R: -------------------------------------------------------------------------------- 1 | test_that("packrat_mode successfully sets the library paths when turned on and off", { 2 | 3 | with_dir(tempdir(), { 4 | 5 | ## Make sure packrat mode is off 6 | if (packrat:::isPackratModeOn()) 7 | packrat::off() 8 | 9 | orig_libs <- getLibPaths() 10 | 11 | # don't use packrat::on so we can avoid the initialization step 12 | packrat:::setPackratModeOn(auto.snapshot = FALSE, clean.search.path = FALSE) 13 | 14 | packrat::off() 15 | 16 | expect_identical(orig_libs, getLibPaths()) 17 | 18 | }) 19 | 20 | }) 21 | -------------------------------------------------------------------------------- /tests/testthat/test-pkg.R: -------------------------------------------------------------------------------- 1 | test_that("inferPackageRecord preserves fields: GitHub", { 2 | # GitHub with no subdir. 3 | df <- as.data.frame(readDcf(test_path("resources/descriptions/github"))) 4 | expect_snapshot(inferPackageRecord(df)) 5 | }) 6 | 7 | test_that("inferPackageRecord preserves fields: GitHub, pkg in subdir", { 8 | # GitHub with subdir. 9 | df <- as.data.frame(readDcf(test_path("resources/descriptions/github_subdir"))) 10 | expect_snapshot(inferPackageRecord(df)) 11 | }) 12 | 13 | test_that("inferPackageRecord preserves fields: GitLab", { 14 | # GitLab with no subdir. 15 | df <- as.data.frame(readDcf(test_path("resources/descriptions/gitlab"))) 16 | expect_snapshot(inferPackageRecord(df)) 17 | }) 18 | 19 | test_that("inferPackageRecord preserves fields: GitLab, pkg in subdir", { 20 | # GitLab with subdir. 21 | df <- as.data.frame(readDcf(test_path("resources/descriptions/gitlab_subdir"))) 22 | expect_snapshot(inferPackageRecord(df)) 23 | }) 24 | -------------------------------------------------------------------------------- /tests/testthat/test-remote-info.R: -------------------------------------------------------------------------------- 1 | test_that("remote_info is correctly generated from a GitHub pkgRecord", { 2 | pkgRecordGithub <- list( 3 | name = 'adder', 4 | source = 'github', 5 | version = '0.9.3.1', 6 | gh_repo = 'adder', 7 | gh_username = 'my-username', 8 | gh_ref = 'HEAD', 9 | gh_sha1 = 'abc123' 10 | ) 11 | expected <- data.frame( 12 | RemoteType = "github", 13 | GithubRepo = "adder", 14 | GithubUsername = "my-username", 15 | GithubRef = "HEAD", 16 | GithubSHA1 = "abc123", 17 | stringsAsFactors = FALSE 18 | ) 19 | expect_identical(getRemoteInfo(pkgRecordGithub), expected) 20 | }) 21 | 22 | test_that("remote_info is correctly generated from a GitHub pkgRecord with a subdirectory", { 23 | pkgRecordGithubSubdir <- list( 24 | name = 'subadder', 25 | source = 'github', 26 | version = '0.9.3.1', 27 | gh_repo = 'sub_adder', 28 | gh_username = 'my-username', 29 | gh_ref = 'HEAD', 30 | gh_sha1 = 'abc123', 31 | gh_subdir = 'subadder' 32 | ) 33 | expected <- data.frame( 34 | RemoteType = "github", 35 | GithubRepo = "sub_adder", 36 | GithubUsername = "my-username", 37 | GithubRef = "HEAD", 38 | GithubSHA1 = "abc123", 39 | GithubSubdir = "subadder", 40 | stringsAsFactors = FALSE 41 | ) 42 | expect_identical(getRemoteInfo(pkgRecordGithubSubdir), expected) 43 | }) 44 | 45 | # GitLab package records will work for Bitbucket too 46 | test_that("remote_info is correctly generated from a GitLab pkgRecord", { 47 | pkgRecordGitlab <- list( 48 | name = 'adder', 49 | source = 'gitlab', 50 | version = '0.9.3.1', 51 | remote_host = 'gitlab.com', 52 | remote_repo = 'adder', 53 | remote_username = 'my-username', 54 | remote_ref = 'HEAD', 55 | remote_sha = 'abc123' 56 | ) 57 | expected <- data.frame( 58 | RemoteType = "gitlab", 59 | RemoteHost = "gitlab.com", 60 | RemoteRepo = "adder", 61 | RemoteUsername = "my-username", 62 | RemoteRef = "HEAD", 63 | RemoteSha = "abc123", 64 | stringsAsFactors = FALSE 65 | ) 66 | expect_identical(getRemoteInfo(pkgRecordGitlab), expected) 67 | }) 68 | 69 | test_that("remote_info is correctly generated from a GitLab pkgRecord with a subdirectory", { 70 | pkgRecordGitlabSubdir <- list( 71 | name = 'subadder', 72 | source = 'gitlab', 73 | version = '0.9.3.1', 74 | remote_host = 'gitlab.com', 75 | remote_repo = 'sub_adder', 76 | remote_username = 'my-username', 77 | remote_ref = 'HEAD', 78 | remote_sha = 'abc123', 79 | remote_subdir = 'subadder' 80 | ) 81 | expected <- data.frame( 82 | RemoteType = "gitlab", 83 | RemoteHost = "gitlab.com", 84 | RemoteRepo = "sub_adder", 85 | RemoteUsername = "my-username", 86 | RemoteRef = "HEAD", 87 | RemoteSha = "abc123", 88 | RemoteSubdir = "subadder", 89 | stringsAsFactors = FALSE 90 | ) 91 | expect_identical(getRemoteInfo(pkgRecordGitlabSubdir), expected) 92 | }) 93 | -------------------------------------------------------------------------------- /tests/testthat/test-restore.R: -------------------------------------------------------------------------------- 1 | remote_info <- data.frame( 2 | RemoteType = "gitlab", 3 | RemoteHost = "gitlab.com", 4 | RemoteRepo = "bread", 5 | RemoteUsername = "breakfaster", 6 | RemoteRef = "HEAD", 7 | RemoteSha = "abc123", 8 | stringsAsFactors = FALSE 9 | ) 10 | 11 | test_that("appendRemoteInfoToDescription modifies DESCRIPTION file", { 12 | src_tmp <- tempfile(fileext = ".tar.gz") 13 | on.exit( 14 | if (file.exists(src_tmp)) unlink(src_tmp, recursive = TRUE), 15 | add = TRUE 16 | ) 17 | dest_tmp <- tempfile(fileext = ".tar.gz") 18 | on.exit( 19 | if (file.exists(dest_tmp)) unlink(dest_tmp, recursive = TRUE), 20 | add = TRUE 21 | ) 22 | 23 | basedir <- test_path("packages/toast") 24 | 25 | tryCatch( 26 | in_dir(dirname(basedir), 27 | suppressWarnings(tar(tarfile = src_tmp, files = basename(basedir), 28 | compression = "gzip", tar = tar_binary())) 29 | ), 30 | error = function(e) { 31 | unlink(src_tmp) 32 | stop(e) 33 | } 34 | ) 35 | 36 | success <- appendRemoteInfoToDescription( 37 | src = src_tmp, 38 | dest = dest_tmp, 39 | remote_info = remote_info 40 | ) 41 | 42 | expect_true(success) 43 | 44 | untarred_tmp <- tempfile() 45 | on.exit( 46 | if (file.exists(untarred_tmp)) unlink(untarred_tmp, recursive = TRUE), 47 | add = TRUE 48 | ) 49 | 50 | untar(dest_tmp, exdir = untarred_tmp, tar = tar_binary()) 51 | if (length(dir(untarred_tmp)) == 1 && 52 | dir.exists(file.path(untarred_tmp, dir(untarred_tmp)))) { 53 | basedir <- file.path(untarred_tmp, dir(untarred_tmp)) 54 | } else { 55 | basedir <- untarred_tmp 56 | } 57 | desc <- readLines(file.path(untarred_tmp, "toast", "DESCRIPTION")) 58 | 59 | expected_desc_tail <- c( 60 | "RemoteType: gitlab", 61 | "RemoteHost: gitlab.com", 62 | "RemoteRepo: bread", 63 | "RemoteUsername: breakfaster", 64 | "RemoteRef: HEAD", 65 | "RemoteSha: abc123" 66 | ) 67 | expect_identical(tail(desc, 6), expected_desc_tail) 68 | getwd() 69 | }) 70 | 71 | test_that("annotatePkgDesc annotates a package description", { 72 | project <- tempfile() 73 | dir.create(project) 74 | lib <- libDir(project) 75 | package <- file.path(lib, "fake") 76 | dir.create(package, recursive = TRUE) 77 | desc <- file.path(package, "DESCRIPTION") 78 | write_dcf( 79 | list( 80 | Package = "fake", 81 | Version = "1.2.3", 82 | InstallAgent = "testthat" 83 | ), 84 | desc 85 | ) 86 | pkgRecord <- list( 87 | name = "fake", 88 | source = "CRAN", 89 | version = "1.2.3" 90 | ) 91 | 92 | annotatePkgDesc(pkgRecord, project) 93 | result <- as.data.frame(readDcf(desc), stringsAsFactors = FALSE) 94 | expect_equal(result$Package, "fake") 95 | expect_equal(result$Version, "1.2.3") 96 | expect_equal(result$InstallAgent, paste('packrat', packageVersion('packrat'))) 97 | expect_equal(result$InstallSource, "CRAN") 98 | }) 99 | -------------------------------------------------------------------------------- /tests/testthat/test-rmarkdown.R: -------------------------------------------------------------------------------- 1 | test_that("Rmd documents with parameters are analyzed", { 2 | skip_on_cran() 3 | 4 | # we need to skip this test if we don't have an up-to-date version of knitr available 5 | if (packageVersion("knitr") < "1.11") 6 | skip("requires knitr 1.11 or greater") 7 | 8 | parameterDocPath <- file.path("resources", "params-example.Rmd") 9 | deps <- packrat:::fileDependencies(parameterDocPath) 10 | expect_true("rmarkdown" %in% deps, "all Rmd docs have an rmarkdown dependency") 11 | expect_true("shiny" %in% deps, "Rmd docs with parameters have a shiny dependency for the customization app") 12 | expect_true("stringr" %in% deps, "dependencies in parameter expressions are extracted") 13 | }) 14 | 15 | test_that("We can discover dependencies with an evaluate hook", { 16 | skip_on_cran() 17 | 18 | path <- "resources/evaluate-deps.Rmd" 19 | deps <- fileDependencies.evaluate(path) 20 | expect_equal(deps, c("abc", "def", "ghi", "jkl")) 21 | 22 | }) 23 | -------------------------------------------------------------------------------- /tests/testthat/test-shiny.R: -------------------------------------------------------------------------------- 1 | test_that("Shiny examples have a shiny dependency", { 2 | skip_on_cran() 3 | skip_if_not_installed("shiny") 4 | 5 | # Confirm packrat believes all example shiny apps are, in fact, shiny apps 6 | examplesPath <- system.file("examples", package = "shiny") 7 | apps <- list.files(examplesPath, full.names = TRUE) 8 | for (app in apps) { 9 | expect_true("shiny" %in% packrat:::appDependencies(app), app) 10 | } 11 | }) 12 | 13 | test_that("projects which use shiny implicitly are detected", { 14 | skip_on_cran() 15 | 16 | # Check that 'shiny' is listed as a dependency for an 17 | # R Markdown document with 'runtime: shiny' 18 | interactiveDocPath <- file.path("resources", "interactive-doc-example.Rmd") 19 | expect_true("shiny" %in% packrat:::fileDependencies(interactiveDocPath)) 20 | }) 21 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | emit <- function(x) cat(x, sep = "\n") 2 | 3 | test_that("dir_copy copies directories", { 4 | 5 | # Work in temporary directory 6 | owd <- getwd() 7 | on.exit(setwd(owd)) 8 | setwd(tempdir()) 9 | 10 | # Create a directory and try to copy it 11 | dir.create("foo") 12 | 13 | file.create("foo/foo1.R") 14 | file.create("foo/foo2.R") 15 | file.create("foo/foo3.R") 16 | file.create("foo/.dotFile") 17 | 18 | dir_copy("foo", "bar", overwrite = TRUE) 19 | expect_identical( 20 | list.files("foo"), 21 | list.files("bar") 22 | ) 23 | expect_error(dir_copy("foo", "bar")) 24 | 25 | }) 26 | 27 | test_that("defer evaluates in appropriate environment", { 28 | 29 | foo <- function() { 30 | emit("+ foo") 31 | defer(emit("> foo"), environment()) 32 | defer(emit("> foo.parent"), parent.frame(1)) 33 | defer(emit("> foo.parent.parent"), parent.frame(2)) 34 | emit("- foo") 35 | } 36 | 37 | bar <- function() { 38 | emit("+ bar") 39 | foo() 40 | emit("- bar") 41 | } 42 | 43 | baz <- function() { 44 | emit("+ baz") 45 | bar() 46 | emit("- baz") 47 | } 48 | 49 | output <- capture.output(baz()) 50 | expected <- c( 51 | "+ baz", 52 | "+ bar", 53 | "+ foo", 54 | "- foo", 55 | "> foo", 56 | "- bar", 57 | "> foo.parent", 58 | "- baz", 59 | "> foo.parent.parent" 60 | ) 61 | 62 | expect_identical(output, expected) 63 | 64 | }) 65 | 66 | test_that("defer captures arguments properly", { 67 | 68 | foo <- function(x) { 69 | defer(emit(x), envir = parent.frame()) 70 | } 71 | 72 | bar <- function(y) { 73 | emit("+ bar") 74 | foo(y) 75 | emit("- bar") 76 | } 77 | 78 | output <- capture.output(bar("> foo")) 79 | expected <- c("+ bar", "- bar", "> foo") 80 | expect_identical(output, expected) 81 | 82 | }) 83 | 84 | test_that("defer works with arbitrary expressions", { 85 | 86 | foo <- function(x) { 87 | defer({ 88 | x + 1 89 | emit("> foo") 90 | }, envir = parent.frame()) 91 | } 92 | 93 | bar <- function() { 94 | emit("+ bar") 95 | foo(1) 96 | emit("- bar") 97 | } 98 | 99 | output <- capture.output(bar()) 100 | expected <- c("+ bar", "- bar", "> foo") 101 | expect_identical(output, expected) 102 | 103 | }) 104 | -------------------------------------------------------------------------------- /tests/testthat/test-with_extlib.R: -------------------------------------------------------------------------------- 1 | test_that("with_extlib successfully works with no packages provided", { 2 | skip_on_cran() 3 | 4 | ## Make sure packrat mode is off 5 | if (packrat:::isPackratModeOn()) 6 | packrat::off() 7 | 8 | orig_libs <- packrat:::getLibPaths() 9 | .libPaths(c(file.path(getwd(), "packages"), orig_libs)) 10 | on.exit(.libPaths(orig_libs), add = TRUE) 11 | 12 | expect_identical(packageVersion("bread"), package_version("1.0.0")) 13 | 14 | # don't use packrat::on so we can avoid the initialization step 15 | packrat:::setPackratModeOn(auto.snapshot = FALSE, clean.search.path = FALSE) 16 | 17 | expect_identical(packrat::with_extlib(expr = packageVersion("bread")), package_version("1.0.0")) 18 | 19 | packrat::off() 20 | 21 | }) 22 | --------------------------------------------------------------------------------