diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index a5935262..08a60658 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -18,16 +18,14 @@ jobs: fail-fast: false matrix: config: - - {os: macOS-latest, r: 'release'} - - # - {os: windows-latest, r: 'release'} - - - {os: ubuntu-22.04, r: 'devel', http-user-agent: 'release'} - - {os: ubuntu-22.04, r: 'release'} - - {os: ubuntu-22.04, r: 'oldrel-1'} - - {os: ubuntu-22.04, r: 'oldrel-2'} - - {os: ubuntu-22.04, r: 'oldrel-3'} - - {os: ubuntu-22.04, r: 'oldrel-4'} + - {os: macos-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + - {os: ubuntu-latest, r: 'oldrel-2'} + - {os: ubuntu-latest, r: 'oldrel-3'} + - {os: ubuntu-latest, r: 'oldrel-4'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} diff --git a/R/recursive-package-dependencies.R b/R/recursive-package-dependencies.R index 857fdb50..9588e5ad 100644 --- a/R/recursive-package-dependencies.R +++ b/R/recursive-package-dependencies.R @@ -43,7 +43,7 @@ getPackageDependencies <- function(pkgs, warning("Package '", pkg, "' found in multiple local repositories; ", "inferring dependencies from package at path:\n- ", shQuote(path)) } - theseDeps <- combineDcfFields(as.data.frame(readDcf(path)), fields) + theseDeps <- combineDcfFields(as.data.frame(readDcf(file.path(path, "DESCRIPTION"))), fields) } else { warning("Package '", pkg, "' not available in repository or locally") return(NULL) diff --git a/R/restore.R b/R/restore.R index a1572705..192c6d17 100644 --- a/R/restore.R +++ b/R/restore.R @@ -961,17 +961,11 @@ appendRemoteInfoToDescription <- function(src, dest, remote_info) { # headers"); hide those suppressWarnings(untar(src, exdir = scratchDir, tar = tar_binary())) - # Find the base directory - basedir <- if (length(dir(scratchDir)) == 1) - file.path(scratchDir, dir(scratchDir)) - else - scratchDir - # Determine the untarred base directory. We're looking to see if the untarred # directory contains only a single directory and if so, we treat that as our # base directory. if (length(dir(scratchDir)) == 1 && - dir.exists(file.path(scratchDir, dir(scratchDir)))) { + is.directory(file.path(scratchDir, dir(scratchDir)))) { basedir <- file.path(scratchDir, dir(scratchDir)) } else { basedir <- scratchDir @@ -988,6 +982,8 @@ appendRemoteInfoToDescription <- function(src, dest, remote_info) { } if (!file.exists(file.path(basedir, "DESCRIPTION"))) { + # This error may indicate a malformed package, or an unexpected directory + # structure inside the tarball. stop("Could not locate DESCRIPTION file in package archive.") } diff --git a/R/testthat-helpers.R b/R/testthat-helpers.R index 8e4ed9db..26ea6f59 100644 --- a/R/testthat-helpers.R +++ b/R/testthat-helpers.R @@ -71,7 +71,7 @@ rebuildTestRepo <- function(testroot = getwd()) { Sys.setenv(R_DEFAULT_SERIALIZE_VERSION = version) }, add = TRUE) - tools::write_PACKAGES(target, subdirs = TRUE) + tools::write_PACKAGES(target, type = "source", subdirs = TRUE) } # "Rebuilds" an empty test repo. @@ -158,7 +158,8 @@ beginTestContext <- function() { Sys.setenv(R_PACKRAT_TESTING = "yes") Sys.setenv(R_PACKRAT_LIBPATHS = paste(.libPaths(), collapse = .Platform$path.sep)) - CRAN <- paste(filePrefix(), normalizePath("repo", winslash = "/"), sep = "") + normalizedRepoPath <- normalizePath("repo", winslash = "/") + CRAN <- paste(filePrefix(), normalizedRepoPath, sep = "") options(repos = c(CRAN = CRAN), pkgType = "source", warn = 0) assign("test.options", options, envir = .packrat) diff --git a/R/utils.R b/R/utils.R index 1ff1cc27..03c85333 100644 --- a/R/utils.R +++ b/R/utils.R @@ -535,6 +535,10 @@ symlink <- function(from, to) { file.exists(to) } +nullfile <- function() { + if (is.windows()) "NUL" else "/dev/null" +} + with_dir <- function(dir, expr) { owd <- getwd() setwd(dir) diff --git a/tests/testthat/test-bitbucket.R b/tests/testthat/test-bitbucket.R index 597abb19..7223a37b 100644 --- a/tests/testthat/test-bitbucket.R +++ b/tests/testthat/test-bitbucket.R @@ -21,15 +21,13 @@ test_that("bitbucketArchiveUrl returns the correct URL", { test_that("bitbucketDownload calls renvDownload in the expected context", { url <- bitbucketArchiveUrl(bitbucket_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() # Testing the effect of the option, rather than just mocking canUseRenvDownload - auth_download_option <- options(packrat.authenticated.downloads.use.renv = TRUE) - on.exit(options(auth_download_option), add = TRUE) - + mockery::stub(bitbucketDownload, "canUseRenvDownload", TRUE) mockery::stub(bitbucketDownload, "bitbucketAuthenticated", TRUE) renv_download_mock <- mockery::mock(destfile) - mockery::stub(bitbucketDownload, "renvDownload", renv_download_mock, depth = 3) + mockery::stub(bitbucketDownload, "renvDownload", renv_download_mock, depth = 5) bitbucketDownload(url, destfile) @@ -39,13 +37,13 @@ test_that("bitbucketDownload calls renvDownload in the expected context", { test_that("bitbucketDownload calls bitbucketDownloadHttr in the expected context", { url <- bitbucketArchiveUrl(bitbucket_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() mockery::stub(bitbucketDownload, "bitbucketAuthenticated", TRUE) mockery::stub(bitbucketDownload, "canUseRenvDownload", FALSE) mockery::stub(bitbucketDownload, "canUseHttr", TRUE) httr_download_mock <- mockery::mock(TRUE) - mockery::stub(bitbucketDownload, "bitbucketDownloadHttr", httr_download_mock, depth = 3) + mockery::stub(bitbucketDownload, "bitbucketDownloadHttr", httr_download_mock, depth = 5) bitbucketDownload(url, destfile) @@ -55,7 +53,7 @@ test_that("bitbucketDownload calls bitbucketDownloadHttr in the expected context test_that("bitbucketDownload calls downloadWithRetries in the expected contexts", { url <- bitbucketArchiveUrl(bitbucket_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() # With auth data but no configured auth-capable method configured @@ -63,7 +61,7 @@ test_that("bitbucketDownload calls downloadWithRetries in the expected contexts" mockery::stub(bitbucketDownload, "canUseRenvDownload", FALSE) mockery::stub(bitbucketDownload, "canUseHttr", FALSE) download_with_retries_mock <- mockery::mock(TRUE) - mockery::stub(bitbucketDownload, "downloadWithRetries", download_with_retries_mock, depth = 3) + mockery::stub(bitbucketDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) bitbucketDownload(url, destfile) @@ -76,7 +74,7 @@ test_that("bitbucketDownload calls downloadWithRetries in the expected contexts" mockery::stub(bitbucketDownload, "canUseRenvDownload", TRUE) mockery::stub(bitbucketDownload, "canUseHttr", TRUE) download_with_retries_mock <- mockery::mock(TRUE) - mockery::stub(bitbucketDownload, "downloadWithRetries", download_with_retries_mock, depth = 3) + mockery::stub(bitbucketDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) bitbucketDownload(url, destfile) diff --git a/tests/testthat/test-downloader.R b/tests/testthat/test-downloader.R index 02fee96c..f65b719e 100644 --- a/tests/testthat/test-downloader.R +++ b/tests/testthat/test-downloader.R @@ -67,7 +67,7 @@ test_that("The same content is returned regardless of download method", { test_that("renvDownload calls renv$download, passing in the values it received", { url <- "https://github.com/my-great-org/cool-repo.tar.gz" - destfile <- "/dev/null" + destfile <- nullfile() type <- "github" renv_download_mock <- mockery::mock(destfile) diff --git a/tests/testthat/test-github.R b/tests/testthat/test-github.R index 3db32214..8fa9299f 100644 --- a/tests/testthat/test-github.R +++ b/tests/testthat/test-github.R @@ -43,15 +43,13 @@ test_that("githubArchiveUrl returns the correct URL", { test_that("githubDownload calls renvDownload in the expected context", { url <- githubArchiveUrl(github_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() # Testing the effect of the option, rather than just mocking canUseRenvDownload - auth_download_option <- options(packrat.authenticated.downloads.use.renv = TRUE) - on.exit(options(auth_download_option), add = TRUE) - + mockery::stub(githubDownload, "canUseRenvDownload", TRUE) mockery::stub(githubDownload, "githubAuthenticated", TRUE) renv_download_mock <- mockery::mock(destfile) - mockery::stub(githubDownload, "renvDownload", renv_download_mock, depth = 3) + mockery::stub(githubDownload, "renvDownload", renv_download_mock, depth = 5) githubDownload(url, destfile) @@ -61,13 +59,13 @@ test_that("githubDownload calls renvDownload in the expected context", { test_that("githubDownload calls githubDownloadHttr in the expected context", { url <- githubArchiveUrl(github_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() mockery::stub(githubDownload, "githubAuthenticated", TRUE) mockery::stub(githubDownload, "canUseRenvDownload", FALSE) mockery::stub(githubDownload, "canUseHttr", TRUE) httr_download_mock <- mockery::mock(TRUE) - mockery::stub(githubDownload, "githubDownloadHttr", httr_download_mock, depth = 3) + mockery::stub(githubDownload, "githubDownloadHttr", httr_download_mock, depth = 5) githubDownload(url, destfile) @@ -77,7 +75,7 @@ test_that("githubDownload calls githubDownloadHttr in the expected context", { test_that("githubDownload calls downloadWithRetries in the expected contexts", { url <- githubArchiveUrl(github_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() # With auth data but no configured auth-capable method configured @@ -85,7 +83,7 @@ test_that("githubDownload calls downloadWithRetries in the expected contexts", { mockery::stub(githubDownload, "canUseRenvDownload", FALSE) mockery::stub(githubDownload, "canUseHttr", FALSE) download_with_retries_mock <- mockery::mock(TRUE) - mockery::stub(githubDownload, "downloadWithRetries", download_with_retries_mock, depth = 3) + mockery::stub(githubDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) githubDownload(url, destfile) @@ -98,7 +96,7 @@ test_that("githubDownload calls downloadWithRetries in the expected contexts", { mockery::stub(githubDownload, "canUseRenvDownload", TRUE) mockery::stub(githubDownload, "canUseHttr", TRUE) download_with_retries_mock <- mockery::mock(TRUE) - mockery::stub(githubDownload, "downloadWithRetries", download_with_retries_mock, depth = 3) + mockery::stub(githubDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) githubDownload(url, destfile) diff --git a/tests/testthat/test-gitlab.R b/tests/testthat/test-gitlab.R index 2094aa36..bba7b0c6 100644 --- a/tests/testthat/test-gitlab.R +++ b/tests/testthat/test-gitlab.R @@ -21,15 +21,13 @@ test_that("gitlabArchiveUrl returns the correct URL", { test_that("gitlabDownload calls renvDownload in the expected context", { url <- gitlabArchiveUrl(gitlab_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() # Testing the effect of the option, rather than just mocking canUseRenvDownload - auth_download_option <- options(packrat.authenticated.downloads.use.renv = TRUE) - on.exit(options(auth_download_option), add = TRUE) - + mockery::stub(gitlabDownload, "canUseRenvDownload", TRUE) mockery::stub(gitlabDownload, "gitlabAuthenticated", TRUE) renv_download_mock <- mockery::mock(destfile) - mockery::stub(gitlabDownload, "renvDownload", renv_download_mock, depth = 3) + mockery::stub(gitlabDownload, "renvDownload", renv_download_mock, depth = 5) gitlabDownload(url, destfile) @@ -39,13 +37,13 @@ test_that("gitlabDownload calls renvDownload in the expected context", { test_that("gitlabDownload calls gitlabDownloadHttr in the expected context", { url <- gitlabArchiveUrl(gitlab_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() mockery::stub(gitlabDownload, "gitlabAuthenticated", TRUE) mockery::stub(gitlabDownload, "canUseRenvDownload", FALSE) mockery::stub(gitlabDownload, "canUseHttr", TRUE) httr_download_mock <- mockery::mock(TRUE) - mockery::stub(gitlabDownload, "gitlabDownloadHttr", httr_download_mock, depth = 3) + mockery::stub(gitlabDownload, "gitlabDownloadHttr", httr_download_mock, depth = 5) gitlabDownload(url, destfile) @@ -55,7 +53,7 @@ test_that("gitlabDownload calls gitlabDownloadHttr in the expected context", { test_that("gitlabDownload calls downloadWithRetries in the expected contexts", { url <- gitlabArchiveUrl(gitlab_pkg_record) - destfile <- "/dev/null" + destfile <- nullfile() # With auth data but no configured auth-capable method configured @@ -63,7 +61,7 @@ test_that("gitlabDownload calls downloadWithRetries in the expected contexts", { mockery::stub(gitlabDownload, "canUseRenvDownload", FALSE) mockery::stub(gitlabDownload, "canUseHttr", FALSE) download_with_retries_mock <- mockery::mock(TRUE) - mockery::stub(gitlabDownload, "downloadWithRetries", download_with_retries_mock, depth = 3) + mockery::stub(gitlabDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) gitlabDownload(url, destfile) @@ -76,7 +74,7 @@ test_that("gitlabDownload calls downloadWithRetries in the expected contexts", { mockery::stub(gitlabDownload, "canUseRenvDownload", TRUE) mockery::stub(gitlabDownload, "canUseHttr", TRUE) download_with_retries_mock <- mockery::mock(TRUE) - mockery::stub(gitlabDownload, "downloadWithRetries", download_with_retries_mock, depth = 3) + mockery::stub(gitlabDownload, "downloadWithRetries", download_with_retries_mock, depth = 5) gitlabDownload(url, destfile) diff --git a/tests/testthat/test-install.R b/tests/testthat/test-install.R index 4f9cef6f..f4dc0611 100644 --- a/tests/testthat/test-install.R +++ b/tests/testthat/test-install.R @@ -21,7 +21,7 @@ test_that("The default list of environment variables is masked correctly", { git_mask_option <- options("packrat.mask.git.service.envvars" = NULL) on.exit(options(git_mask_option), add = TRUE, after = FALSE) - subprocess_output <- R("-e 'Sys.getenv()'", return_output = TRUE) + subprocess_output <- R('-e "Sys.getenv()"', return_output = TRUE) # Check to see if the masked envvar names appear in the subprocess output. found_in_output <- sapply(names(new_envvars), function(x) any(grepl(x, subprocess_output))) @@ -52,7 +52,7 @@ test_that("The default list of masked environment variables can be disabled", { git_mask_option <- options("packrat.mask.git.service.envvars" = FALSE) on.exit(options(git_mask_option), add = TRUE, after = FALSE) - subprocess_output <- R("-e 'Sys.getenv()'", return_output = TRUE) + subprocess_output <- R('-e "Sys.getenv()"', return_output = TRUE) # Check to see if the masked envvar names appear in the subprocess output. found_in_output <- sapply(names(new_envvars), function(x) any(grepl(x, subprocess_output))) @@ -70,7 +70,8 @@ test_that("Environment variables appear in an R subprocess", { user_mask <- options("packrat.masked.envvars" = NULL) on.exit(options(user_mask), add = TRUE, after = FALSE) - subprocess_output <- R("-e 'Sys.getenv()'", return_output = TRUE) + subprocess_output <- R('-e "Sys.getenv()"', return_output = TRUE) + found_in_output <- sapply(names(new_envvars), function(x) any(grepl(x, subprocess_output))) expect_true(all(found_in_output), info = print(subprocess_output)) }) @@ -86,7 +87,8 @@ test_that("User-specified masked envvars do not appear in an R subprocess", { user_mask <- options("packrat.masked.envvars" = names(new_envvars)) on.exit(options(user_mask), add = TRUE, after = FALSE) - subprocess_output <- R("-e 'Sys.getenv()'", return_output = TRUE) + subprocess_output <- R('-e "Sys.getenv()"', return_output = TRUE) + found_in_output <- sapply(names(new_envvars), function(x) any(grepl(x, subprocess_output))) # Read `any(found_in_output)` as "Are any of the outputs TRUE?" @@ -125,7 +127,7 @@ test_that("Git and user-specified variables can be masked while other variables masked_names <- names(new_envvars)[1:length(new_envvars) - 1] unmasked_name <- names(new_envvars)[length(new_envvars)] - subprocess_output <- R("-e 'Sys.getenv()'", return_output = TRUE) + subprocess_output <- R('-e "Sys.getenv()"', return_output = TRUE) # Check masked vars not_expected <- sapply(masked_names, function(x) any(grepl(x, subprocess_output))) diff --git a/tests/testthat/test-packrat.R b/tests/testthat/test-packrat.R index 74a874f4..e92e7ac2 100644 --- a/tests/testthat/test-packrat.R +++ b/tests/testthat/test-packrat.R @@ -277,6 +277,7 @@ withTestContext({ test_that("Packages restored from GitLab have RemoteType+RemoteHost in their DESCRIPTION", { skip_on_cran() + skip_on_os("windows") # Windows tar.exe fails to extract the archive received here. projRoot <- cloneTestProject("falsy-gitlab") # ignore R version warnings